Active Server Pages

Active Server Pages (ASP) 是服务器端的脚本编写环境，您可用它来创建动态 Web 页或生成功能强大的 Web 应用程序。ASP 页是包括 HTML 标记、文本和脚本命令的文件。ASP 页可调用 ActiveX 组件来执行任务，例如连接到数据库或进行商务计算。通过 ASP，可为您的 Web 页添加交互内容或用 HTML 页构成整个 Web 应用程序，这些应用程序使用 HTML 页作为您的客户的界面。

本节的主题是介绍 Active Server Pages，解释 Active Server Pages 脚本的基本概念，并讨论诸如如何维持状态之类的更复杂的应用程序问题。

本节包括：

  • 介绍 Active Server Pages：介绍 ASP 并描述该版本中的新特征。
  • 使用脚本语言：提供编写脚本所需的基本信息，包括语言的语法信息。
  • 编写简单脚本：提供编写执行基本任务的脚本的信息，例如从 HTML 表格获取信息。
  • ASP 应用：提供编写脚本所需的更复杂的信息，例如管理会话状态。

本节不包括以下信息：

  • 更高级的主题信息，例如使用会话状态。请参阅 ASP 应用程序
  • 内建 ASP 对象的参考页。
  • 有关 ASP 组件的参考页。
  • 构建您自己的 ASP 组件。
  • VBScript 参考页。
  • JScript 参考页。
  • SDK 提供的示例脚本。


Active Server Pages 简介

Active Server Pages（ASP）使生成 Web 动态内容及构造功能强大的 Web 应用程序的工作变得十分简单。不论是 Web 设计人员还是 Web 开发人员，通过这部分的介绍都将了解到 ASP 能为您提供多大的帮助。

这部分包括：

  • 关于 Active Server Pages：提供了关于 Active Server Pages 的概述。
  • ASP 的新内容：描述了此版本中增加的新内容。

这部分不包括下列信息：

  • 关于编写 ASP 脚本基本概念的信息。
  • 关于编写执行基本任务脚本的信息。
  • 关于编写其他高级脚本的信息。
  • ASP 对象和组件以及脚本语言的参考页。


关于 ASP

Microsoft® Active Server Pages (ASP) 是服务器端脚本编写环境，使用它可以创建和运行动态、交互的 Web 服务器应用程序。使用 ASP 可以组合 HTML 页、脚本命令和 ActiveX 组件以创建交互的 Web 页和基于 Web 的功能强大的应用程序。ASP 应用程序很容易开发和修改。

HTML 编写人员

如果您是位 HTML 编写人员，您将发现 ASP 脚本提供了创建交互页的简便方法。如果您曾想从 HTML 表格中收集数据，或用顾客的姓名个人化 HTML 文件，或根据浏览器的不同使用不同的特性，您会发现 ASP 提供了一个出色的解决方案。以前，要想从 HTML 表格中收集数据，就不得不学习一门编程语言来创建一个 CGI 应用程序。现在，您只要将一些简单的指令嵌入到您的 HTML 文件中，就可以从表格中收集数据并进行分析。您再不必学习完整的编程语言或者单独编译程序来创建交互页。

随着不断掌握使用 ASP 和脚本语言的技巧，您可以创建更复杂的脚本。对于 ASP，您可以便捷地使用 ActiveX 组件来执行复杂的任务，比如连接数据库以存储和检索信息。

有经验的脚本编写人员

如果您已经掌握一门脚本语言，如 VBScript、JavaScript 或 PERL，而且您已经了解使用 ASP 的方法。只要安装了符合 ActiveX 脚本标准的相应脚本引擎，就可以在 ASP 页中使用任何一种脚本语言。ASP 带有 Microsoft® Visual Basic® Scripting Edition （VBScript）和 Microsoft® JScript™ 的脚本引擎，这样您可以立即开始编辑脚本。PERL、REXX 和 Python 的 ActiveX 脚本引擎可以从第三方开发人员处获得。

Web 开发人员

如果您已经掌握了一门编程语言，如 Visual Basic，您将发现 ASP 是快速创建 Web 应用程序的一个非常灵活的方法。通过向 HTML 中添加脚本命令，您能够创建应用程序的 HTML 接口。通过创建自己的 ActiveX 组件，可以将应用程序中的商业逻辑封装到能够从脚本、其他组件或从其他程序中调用的模块。

使用 ASP 进行计算的 Web 可转化为有形的利益，它使 Web 供应商能够提供交互的商业应用而不仅仅是发布内容。例如，旅行社能够比公布航空时刻表做得更多；用 ASP 脚本可以让客户察看现有的航班、比较费用并预定座位。

包含在 Windows NT Option pack 中的 Microsoft Transaction Server（MTS）可以降低在服务器上构造程序的复杂性和费用。MTS 可以解决开发那些保密性强的、可分级的以及可靠的 Web 应用程序的复杂性问题。

Active Server Pages 模型

浏览器从 Web 服务器上请求 .asp 文件时，ASP 脚本开始运行。然后 Web 服务器调用 ASP，ASP 全面读取请求的文件，执行所有脚本命令，并将 Web 页传送给浏览器。

由于脚本在服务器上而不是在客户端运行，传送到浏览器上的 Web 页是在 Web 服务器上生成的。所以不必担心浏览器能否处理脚本：Web 服务器已经完成了所有脚本的处理，并将标准的 HTML 传输到浏览器。由于只有脚本的结果返回到浏览器，所以服务器端脚本不易复制。用户看不到创建他们正在浏览的页的脚本命令。


ASP 的新功能

Active Server Pages 在功能方面有所增强，更易于开发应用程序。

  • Microsoft 脚本调试程序。 您可以使用脚本调试程序调试 .asp 文件。请参阅调试 ASP 脚本。
  • 事务性脚本。 ASP 页和页中使用的对象可以运行于事务环境之下。在页上的全部工作只有两种结果：提交或终止。事务可以保护应用程序免于因失败而导致数据丢失。请参阅创建事务性脚本。
  • 管理工具。 许多应用程序设置可在 Internet 服务管理器上进行，这是 Internet Information Server 和 Personal Web Server（在 Windows NT Workstation 上）的管理工具。
  • 隔离 ASP 应用程序。 您可以隔离 ASP 应用程序以便它们能在 Web 服务器上独立的内存空间内运行。万一某个应用程序失败时，可以保护其他应用程序和 Web 服务器。它也使您可以在不停止 Web 服务器的情况下，停止一个应用程序或从内存中卸载其组件。
  • 文件上载。 浏览器可以通过 Posting Acceptor 应用程序将文件上载到 Web 服务器。可以编写 ASP 脚本来发送带有从 Posting Acceptor 传来的信息的 email，如每一个上载文件的位置和名称。请参阅 Posting Accepter 文档（在 Microsoft Site Server Express 的目录表中）。
  • 新的 ASP 组件。 ASP 提供了新的基础组件。
  • 应用程序根目录的改变。 ASP 应用程序的根目录在您的 Web 站点上可以是物理目录。以前，根目录必须映射为虚拟目录。现在可以用 Internet 服务管理器指示 ASP 应用程序的根目录。必须将 .asp 文件置于应用程序树中，Web 服务器才能检测文件的改变并且自动重装它们。
  • 支持 Internet Explorer 4.0 通道和 Web 预测。 当 ASP 要发送包含通道定义命令的文件时，它会自动告诉 Internet Explorer 4.0。使用 ASP 很容易就能生成通道定义 (.cdf) 文件。
  • 支持 HTTP 1.1 协议。 Internet Information Server 和 Personal Web Server 支持 HTTP 1.1 协议。在响应支持 HTTP 1.1 的浏览器（例如 Internet Explorer 4.0）时，这一支持可使 ASP 利用新协议的高效率。例如，当向浏览器返回页的时候，ASP 使用大块转换编码以提高网络效率。


使用脚本语言

Active Server Pages 提供了一个在 HTML 页中使用现有脚本语言如 Microsoft VBScript 和 Microsoft JScript 的框架。本节将解释如何创建 ASP 页、如何添加脚本语言语句以及如何执行创建对象实例等基本任务。虽然这些主题介绍了一些脚本和编程的概念，但其用意并非是教您一门脚本语言。Microsoft 的脚本语言提供自己的文档，许多其他的有关脚本的书籍可从您当地的图书商处获得。不管您是初学者还是经验丰富的脚本编写人员，都应该浏览这些主题以便学习基本的框架和在 ASP 页中使用脚本语言的语法。如果您是位新手，就该通过书本和课程来掌握这些语言。

本节包括：

  • 创建 ASP 页：描述 ASP 页并解释如何给页添加脚本命令。
  • 使用脚本语言：解释如何设置主语言以及如何在服务器脚本中使用 VBScript 和 JScript。
  • 使用变量和常量：介绍在 ASP 脚本中使用变量以及解释如何获取常量定义。
  • 编写过程：解释如何定义过程（函数和子程序）以及如何从 ASP 脚本中调用它们。
  • 使用组件和对象：解释如何创建由 ActiveX 组件提供的对象的实例、如何使用 ASP 内建对象以及如何使用对象的方法和属性。
  • 使用集合：解释如何访问内建对象的集合中的项目，包括遍历整个集合。
  • 设置对象作用域：解释对象的作用域并描述如何创建会话或应用程序作用域对象。
  • ASP 内建对象：通过到详细信息的链接提供 ASP 内建对象的快速浏览。
  • ActiveX 组件：通过到详细信息的链接提供 ASP 提供的 ActiveX 组件的快速浏览。

本节不包含下列信息：

  • 关于编写执行基本任务的脚本的信息。
  • 关于编写更高级脚本的信息。
  • ASP 对象和组件以及脚本语言的参考页。


创建 ASP 页

Active Server Pages（ASP）文件是以 .asp 为扩展名的文本文件，这个文本文件可以包括下列部分的任意组合：

  • 文本
  • HTML 标记
  • ASP 脚本命令

创建 .asp 文件非常容易。如果要在 HTML 文件中添加脚本，只需将该文件的扩展名 .htm 或 .html 替换为 .asp 就可以了。要使 .asp 文件可用于 Web 用户，请将这个新文件保存在 Web 站点上的目录中（请确定启用了该目录的脚本和执行权限）。使用浏览器查看该文件时，可以看到 ASP 处理并返回了 HTML 页。现在可以在 .asp 文件中添加脚本命令了。

注意 因为 .asp 文件需要额外的处理，请不要将所有的 HTML 页都转换为 ASP 页。应该只将包含脚本命令的文件转换为 .asp 文件。.asp 和 .htm 文件可以放置在相同的目录中。

使用任何的文本编辑器都可以创建 .asp 文件。使用那些带有 ASP 增强支持的编辑器将更能提高效率，如 Microsoft® Visual InterDev™ 。如果您从未使用过 HTML，请考虑先使用 Microsoft FrontPage 。使用 FrontPage 创建文档和格式化文本就象使用文字处理工具一样简单。接下来还可以使用 Insert Script 命令在 FrontPage 创建的 HTML 页中加入简单的 ASP 命令。

加入 Script 命令

脚本是一系列的命令和指令。与 HTML 标签不同，script 命令指示 Web 服务器执行操作，而 HTML 标签只是简单地格式化文本或读取图形、视频及音频文件。Script 命令可以在变量中存储用户名，在返回到浏览器的页中显示用户名或将用户名存储在数据库中。

脚本命令通过定界符与文本区别开来。定界符是字符或一串字符，它标志单元开始或结束。HTML 使用定界符——小于号（<）和大于号（>）括入 HTML 标签。

ASP 使用定界符 <% 和 %> 括入脚本命令。您可以在定界符中括入任何命令，只要这些命令对正在使用的脚本语言有效。下面的例子展示了包含脚本命令的简单的 HTML 页：

<HTML>
<BODY>
This page was last refreshed on <%= Now %>.
</BODY>
</HTML>

VBScript 函数 Now 返回当前的日期和时间。Web 服务器处理该页时，会使用当前的日期和时间替换 <%= Now %> 并且将该页返回到浏览器：

This page was last refreshed on 8/1/97 2:20:00 PM.

定界符括入的命令被称为主脚本命令。这些命令被主脚本语言处理。在脚本定界符中使用的任何命令都必须对主脚本语言有效。默认情况下，主脚本语言是 VBScript。要设置另一种语言。

如果您已经熟悉了客户端脚本编写（编写在浏览器上运行的脚本），请注意不要用 HTML <SCRIPT> 元素括入表达式。在编写服务器端脚本时，只用 <SCRIPT> 元素在主脚本语言外的其他语言中定义过程。

合成 HTML 和脚本命令

在 ASP 定界符中可以包含任何在主脚本语言中合法的语句、表达式、过程或操作符。在 VBScript 和其他脚本语言中，语句是语法完整的单元，该单元表达某项活动、声明或定义。下面的条件语句 If...Then...Else 是一条常见的 VBScript 语句。

<%
If Time >= #12:00:00 AM# And Time < #12:00:00 PM#  Then
  Greeting = "Good Morning!"
Else
  Greeting = "Hello!"
End If
%>

<%= Greeting %>

这条语句将值 "Good Morning!" 或值 "Hello!" 存储在变量 greeting 中。<%= Greeting %> 命令将当前的变量值发送到浏览器中。

这样，在（Web 服务器所在时区的）正午 12 点前浏览该脚本的用户将看到：

Good Morning!

在正午 12 点或以后浏览此脚本的用户将看到：

Hello!

在语句的不同部分之间可以加入 HTML 文本。例如，下面的脚本在If...Then...Else 语句中加入了 HTML，产生了与上面脚本同样的结果：

<% If Time >= #12:00:00 AM# And Time < #12:00:00 PM# Then %>
Good Morning!
<% Else %>
Hello!
<% End If %>

如果条件为真——也就是说，如果时间为午夜、午夜以后或者中午以前，那么 Web 服务器将跟随条件（“Good Morning”）的 HTML 发送到浏览器；否则，将跟随 Else 的 HTML（“Hello”）发送到浏览器。这种混合 HTML 和脚本命令的方式可以方便地将 If...Then...Else 语句变换为几行 HTML 文本。如果要在 Web 页上显示多处问候，前一个例子更为有用。只需要设置一次变量，就可以重复显示。

最好从脚本命令中将 HTML 文本返回到浏览器，而不用脚本命令散布 HTML 文本。要将文本返回到浏览器，请使用 ASP 的内建对象 Response。下面的例子可以产生与前一个脚本同样的结果：

<%
If Time >= #12:00:00 AM# And Time < #12:00:00 PM#  Then
  Response.Write "Good Morning!"
Else
  Response.Write "Hello!"
End If
%>

Response.Write 将跟随的文本发送到浏览器。要动态构造返回浏览器的文本，请在语句中使用 Response.Write。例如，可能要构造包含一些变量值的字符串。在 使用组件和对象 以及 向浏览器传送内容 中了解到更多有关 Response 对象和一般对象的信息。现在，先了解将脚本命令插入到 HTML 页中的几种方法。

在 ASP 定界符中可以包含用默认主脚本语言编写的过程。

如果正在使用 JScript 命令，可以插入花括号指示语句块直接进入 ASP 命令，而不用考虑它是否夹杂着 HTML 标签和文本。例如：

<% if (screenresolution == "low") { %>
This is the text version of a page.
<% } else { %>
This is the multimedia version of a page.
<% } %>

使用 ASP 指令

ASP 提供了您使用的脚本语言以外的指令。这是一些输出指令和处理指令。

ASP 的输出指 <%= expression %> 显示表达式的值。这个输出指令等同于使用 Response.Write 显示信息。例如，输出表达式 <%= sport %> 将文字 climbing（变量当前的值）传送到浏览器。

ASP 处理指令 <%@ keyword %> 为 ASP 提供处理 .asp 文件所需的信息。例如，下面的指令将 VBScript 设为该页的主脚本语言：

<%@ LANGUAGE=VBScript %>

处理指令必须出现在 .asp 文件的第一行。不要将处理指令放在包含 #include 语句的文件中。必须在 at 标记（@）和关键字之间加入一个空格。处理指令有下列关键字：

  • LANGUAGE 关键字设置页的脚本语言。
  • CODEPAGE 关键字设置页的代码页（字符编码）。
  • LCID 关键字设置页的现场标识符。
  • TRANSACTION 关键字指定将在事务处理环境下运行的页。
  • ENABLESESSIONSTATE 关键字指定 ASP 页是否使用会话状态。

可以在单个指令中包含多个关键字；关键字/值对之间必须由空格分开。不要在等号（=）左右加入空格。下面的例子中设置了脚本语言和代码页：

<%@ LANGUAGE=JScript CODEPAGE=932 %>

在脚本中的空白字符

如果您的主脚本语言是 VBScript 或者 JScript，ASP 从指令中删除空白字符。使用其他脚本语言时，ASP 保留空白字符，这样那些需要使用位置和缩进的语言，如 Python 就可以被正确解释了。空白字符包括空格、制表符、回车和换行符。

使用 VBScript 和 JScript 时，在打开定界符之后和关闭定界符之前使用空白字符更容易阅读命令。下面的命令都是合法的：

<% Color = "Green" %>

<%Color="Green"%>

<%
Color = "Green"
%>

ASP 将一个语句的关闭定界符与下一个语句的打开定界符之间的空白字符删除。要保留两个语句间的空白字符，比如在句子中显示变量值的时候，请使用 HTML 不间断空符（&nbsp;）。例如：

<%
'Define two variables with string values.
Hello = "Hello"
World = "World"
%>

<P>My response is to say "<%= Hello %>&nbsp;<%= World %>." </P>


使用脚本语言

脚本语言是介于 HTML 和 Java、C++ 和 Visual Basic 之类的编程语言之间的语言。HTML 通常用于格式化文本和链接网页。编程语言通常用于向计算机发送一系列复杂指令。脚本语言也可用来向计算机发送指令，但它们的语法和规则没有可编译的编程语言那样严格和复杂。脚本语言主要用于格式化文本和使用以编程语言编写的已编译好的组件。

Active Server Pages 使 Web 开发商用多种脚本语言编写完整的过程成为可能。事实上，在单个 .asp 文件内部就可以使用多种脚本语言。另外，由于脚本是在服务器端读取和处理的，所以请求 .asp 文件的客户端浏览器并不需要支持脚本。

您可以使用任意一种其相应的脚本引擎已安装在 Web 服务器上的脚本语言。脚本引擎是处理用某种语言书写的命令的程序。Active Server Pages 带有两个脚本引擎：Microsoft Visual Basic Scripting Edition (VBScript) 和 Microsoft JScript。您也可以安装和使用其他的脚本语言引擎，例如 REXX 和 Perl。

如果您已经是 Visual Basic 程序员，就可以马上使用 VBScript，它是 Visual Basic 的子集。如果您是 Java、C 或 C++ 程序员，您会发现 JScript 语法对您来说是熟悉的，虽然 JScript 与 Java 或 C 并没有联系。

如果您熟悉其他脚本语言，例如 REXX 或 Perl，您可获取和安装相应的脚本引擎，这样就可以使用您熟悉的脚本语言了。Active Server Pages 是 ActiveX 脚本的宿主。要使用一种语言，必须安装脚本引擎，该引擎必须遵循 ActiveX 脚本标准并作为一个 COM （组件对象模型）对象驻留在 Web 服务器上。

设置主脚本语言

ASP 主脚本语言是用来处理在分界符 <% 和 %> 内部的命令的语言。默认时，主脚本语言是 VBScript。您可以将任何一种具有脚本引擎的脚本语言作为主脚本语言。您可以逐页设置主脚本语言，也可以在 ASP 应用程序中设置所有页的主脚本语言。

为某页设置语言

要设置单个页的主脚本语言，可将 <%@ LANGUAGE %> 指令添加到 .asp 文件的开头。该指令的语法是：

<%@ LANGUAGE=ScriptingLanguage %>

其中 ScriptingLanguage 就是您所设置的页的主脚本语言。如果对某页进行了设置，那么该页将忽略在应用程序中对所有页的全局设置。

请遵循使用 ASP 指令的指导。详细信息，请参阅创建 ASP 页。

注意 要将不支持Object.Method 语法的语言作为主脚本语言使用，必须先创建 LanguageEngines 注册表键。

为应用程序设置语言

在应用程序中，如要为所有页设置主脚本语言，可在 Internet 服务管理器的“App 选项”选项卡上设置“默认的 ASP 语言”属性。

在服务器上使用 VBScript 和 JScript

在服务端通过 ASP 使用 VBScript 时，两个 VBScript 特征将失效。由于 Active Server Pages 脚本是在服务器端执行的，表示用户接口的元素的 VBScript 语句 InputBox 和 MsgBox 将不被支持。另外，在服务器端的脚本中，请不要使用 VBScript 函数 CreateObject 和 GetObject。而要使用 Server.CreateObject，这样 ASP 就可以跟踪对象实例了。用 CreateObject 或 GetObject 创建的对象不能访问 ASP 内建对象，也不能参与事务处理。该规则的一个例外是如果您使用的是 Admin 对象和 Java monikers。

包含注释

由于 ASP 脚本是在服务器端处理的，所以即使客户端的浏览器不支持脚本语言，也不必通过包含进 HTML 注释标记来隐藏脚本，但客户端的脚本则通常需要这样处理。在内容送到浏览器之前，所有 ASP 命令都已被处理好了。您可用 HTML 注释将注释加进 HTML 页。注释将返回给浏览器，若用户浏览 HTML 源文件，就可以看见。

VBScript 注释

VBScript 支持撇号型注释。与 HTML 注释不同，当处理脚本时，它们将被删除，而不是被送到浏览器。

<%
'This line and the following two are comments.
'The PrintTable function prints all
'the elements in an array.
Call PrintTable(myarray())
%>

输出表达式不能包括注释。例如，下面的第一行将正常运行，而第二行则不能，因为它是以 <%= 开头的。

<% i = i +1 'this increments i. This script will work. %>

<%= name 'this prints the variable name. This script will fail. %>

JScript 注释

JScript 支持 // 注释符。每一个注释行中都必须使用该注释符。

<% Call PrintDate %>
<SCRIPT LANGUAGE=JScript RUNAT=Server>
// This is a definition for the procedure PrintDate.
function PrintDate()
{
  var x
  x = new Date()
  // This line sends the current date to the browser,
  // translated to a string.
  Response.Write(x.toString())
}
</SCRIPT>

大小写敏感性

VBScript 不区分大小写。例如，您可以用 Request 或 request 来引用 ASP Request 对象。不区分大小写的后果是您不能用大小写来区分变量名。例如，您不能创建两个名为 Color 和 color 的单独变量。

JScript 区分大小写。要在脚本中使用 JScript 关键字，就必须按参考页中所示的大小写来书写。例如，用 date 来代替 Date 将导致错误。在 JScript 中，对象名必须大写；方法名和属性名可大写也可小写。本文所示的 ASP 内建对象的情况将在 JScript 命令中正常工作。


使用变量和常量

变量是计算机内存中已命名的存储位置，其中包含了数字或字符串等数据。变量包含的信息被称为变量的值。变量使用用户便于理解脚本操作的名称为用户提供了一种存储、检索和操作数据的途径。

声明和命名变量

命名和声明变量应遵循脚本语言的规则及指导。即使在使用变量前不需要去声明变量，也应养成在编程时声明变量的良好习惯，因为这样有助于防止错误发生。声明一个变量意味着告诉脚本引擎，有一个特定名称的变量，这样就可以在脚本中引用该变量。

VBScript

VBScript 并不需要声明变量，但在使用所有变量前声明它们是一种好的脚本书写习惯。要在 VBScript 中声明变量，请用 Dim、 Public 或 Private 语句。例如：

<% Dim UserName %>

可以在需要显式声明变量的 .asp 文件中用 VBScript Option Explicit 语句。Option Explicit 必须在任何一个 ASP 指令之后及任何一个 HTML 文本或脚本命令之前出现。该语句仅影响用 VBScript 书写的 ASP 命令，而不会影响 JScript 命令。

JScript

Microsoft JScript 仅当变量为本地过程变量时才需声明，但在使用所有变量前声明它们是一种好的脚本书写习惯。要声明一个变量，请使用 var 语句。例如：

<% var UserName; %>

变量作用域

变量的作用域即生命期，决定哪些脚本命令可访问变量。在过程内部声明的变量具有局部作用域。每执行一次过程，变量就被创建然后消亡。而过程外部的任何命令都不能访问它。在过程外部声明的变量具有全局作用域，其值能被 ASP 页上的任何脚本命令访问和修改。

声明变量时，局部变量和全局变量可以有相同的名称。而改变其中一个的值并不会改变另一个的值。如果没有声明变量，则可能不小心会改变一个全局变量的值。例如，以下脚本命令返回值 1，虽然有两个名为 Y 变量：

<%
Dim Y
Y = 1
Call SetLocalVariable
Response.Write Y

Sub SetLocalVariable
  Dim Y
  Y = 2
End Sub
%>

由于变量没有显式声明，以下的脚本命令将返回 2。当过程调用将 Y 设置为 2 时，脚本引擎认为该过程是要修改全局变量：

<%
Y = 1
Call SetLocalVariable
Response.Write Y

Sub SetLocalVariable
  Y = 2
End Sub
%>

养成显式声明所有变量的编程习惯可以避免许多问题。尤其在当您用 #include 语句将文件包含进 ASP 主页时，就显得更为重要。一个独立文件中被包含的脚本是被当作整个包含它的文件的一部分来处理的。用不同的名称来命名主脚本和被包含脚本中用到的变量，这容易被遗忘，除非声明变量。

为变量赋予会话或应用程序作用域

全局变量仅在单个 ASP 页中可用，要使它在单个 ASP 页之外可用，就必须为变量赋予会话或应用程序作用域。会话作用域变量对一个用户所请求的 ASP 应用程序中的所有页都是可用的。应用程序作用域变量也如此。对单个用户来说，会话变量是存储信息的最佳途径，例如，首选项、用户名或用户标识。对于一个特殊应用程序的所有用户，应用程序作用域是存储信息的最佳途径，例如，应用程序特定的问候语或应用程序所需的初始值。

ASP 提供两个内建对象来让您存储变量：Session 对象和 Application 对象。

您也可以创建具有会话或应用程序作用域的对象实例。详细信息，请参阅设置对象作用域。

会话作用域

要为变量赋予会话作用域，将该变量存储到 Session 对象中即可，方法是为该对象的已命名条目指派一个值。例如，以下命令将两个新的变量存储到 Session 对象中。

<%
Session("FirstName") = "Jeff"
Session("LastName") = "Smith"
%>

要 Session 对象中检索信息，可以用输出指令 (<%=) 或 Response.Write 访问已命名的条目。以下示例用输出指令显示 Session("FirstName") 的当前值：

Welcome <%= Session("FirstName") %>

可在 Session 对象中存储用户首选项，然后就可以访问这些首选项，从而决定将哪一页返回给用户。例如，您可以允许用户在应用程序的第一页指定纯文本内容，然后将这一选择应用到用户在该应用程序中访问的所有后续页。

<% If Session("ScreenResolution") = "Low" Then %>
This is the text version of the page.
<% Else %>
This is the multimedia version of the page.
<% End If %>

应用程序作用域

要为变量赋予应用程序作用域，将该变量存储到 Application 对象中即可，方法是为该对象的已命名条目指派一个值。例如，以下命令将一个应用程序特定的问候语存储到Application 对象中：

<% Application("Greeting") = "Welcome to Exploration Air" %>

要从 Application 对象中检索信息，可以使用 ASP 输出指令 (<%=) 或 Response.Write 从该应用程序的任意后续页中访问已命名条目。以下示例用输出指令显示 Application("Greeting") 的值：

<%= Application("Greeting") %>

使用常量

常量是用来代替一个数或字符串的名称。一些随 ASP 提供的基本组件，例如 ActiveX Data Objects (ADO)，定义了您在脚本中可以使用的常量。组件可在一个组件类型库中声明常量，组件类型库是一个包含 ActiveX 组件所支持的对象和类型的信息的文件。一旦在 Global.asa 文件中声明了一个类型库，您就可以在该应用程序的任意页中使用已定义的常量。

可在 Global.asa 中用 <METADATA> 标记为应用程序声明类型库。例如，要声明 ADO 类型库，可用以下语句：

<!--METADATA TYPE="typelib"
FILE="c:\program files\common files\system\ado\msado15.dll"
-->

这样，您就可以在与 Global.asa 文件相同的应用程序的中使用 ADO 常量。在下面的示例中，adOpenKeyset 和 adLockOptimistic 是 ADO 常量：

'Create and Open Recordset Object
Set RsCustomerList = Server.CreateObject("ADODB.Recordset")
RsCustomerList.ActiveConnection = OBJdbConnection
RsCustomerList.CursorType = adOpenKeyset
RsCustomerList.LockType = adLockOptimistic

在以前版本的 ASP 中，一些组件在文件中提供常量定义，每个使用那些组件的 ASP 文件必须包含该文件。用 #include 指令来包含常量定义的用法仍被支持，但使用类型库通常更方便并且能使脚本更易于升级。在以后版本的 ASP 中，组件可能将不再提供常量定义文件。

您可以定义自己的常量。在 VBScript 中，用 Const 语句，在 JScript 中，用 var 语句。如果在多个 ASP 页中使用常量，可在独立的文件中放置常量，然后将其包含进每一个使用该常量的 ASP 文件中去。


编写过程

过程是一组能执行指定任务且具有返回值的脚本命令。您可以定义自己的过程，然后在脚本中反复调用它们。

您可以将过程定义放在调用过程的 .asp 文件中，也可以将通用过程放在一个共享的 .asp 文件中，然后用 SSI #include 指令将其包含进其他调用其过程的 .asp 文件中。您还可选择另一种方法，即把这些功能打包在 ActiveX 组件中。

定义过程

过程定义可出现在 <SCRIPT> 和 </SCRIPT> 标记内部且必须遵循声明脚本语言的规则。如果过程所用的语言与主脚本语言不同，则要使用 <SCRIPT> 元素。主脚本语言中的过程用脚本分界符 (<% 和 %>) 分隔。

用 HTML <SCRIPT> 标记时，必须使用两个属性来保证服务器端能够处理脚本。使用 <SCRIPT> 标记的语法是：

<SCRIPT RUNAT=SERVER LANGUAGE=JSCRIPT>
  procedure definition
</SCRIPT>

RUNAT=SERVER 属性通知 Web 服务器在服务器上处理脚本。若不设置该属性，脚本将由客户端浏览器处理。LANGUAGE 属性决定此脚本块所用的脚本语言。您可以指定任何一种具有脚本引擎的语言。请使用 VBSCRIPT 指定 VBScript； 用 JSCRIPT 指定 JScript。若不设置 LANGUAGE 属性，将用主脚本语言解释此脚本块。

脚本块中的命令必须用所选的脚本语言形成一个或多个完整的过程。例如，以下命令定义 JScript 过程 MyFunction。

<HTML>
<SCRIPT RUNAT=SERVER LANGUAGE=JSCRIPT>
  function MyFunction()
  {
      Response.Write("MyFunction Called")
  }
</SCRIPT>

要点 不要在服务器端的 <SCRIPT> 标记内部包含任何不属于某个完整过程的一部分的脚本命令。由于执行顺序不可预测，所以不属于过程的命令可能会导致意外结果。另外，在过程内不能使用 ASP 输出表达式 <%=，而应使用 Response.Write。

调用过程

要调用过程，在命令中包含过程名即可。如果从 VBScript 中调用 JScript 过程，就必须在过程名后加上括号；如过程没有变量，就用空括号。不管是从 JScript 调用 VBScript 还是调用 JScript 过程，在过程后总要加上括号。

对于 VBScript，调用过程时要用 Call 关键字。如果调用的过程需要括号，变量表必须放在括号内。如果省略 Call 关键字，也必须省略变量表外的括号。如果用 Call 语法调用任何内建的或用户自定义的函数，函数的返回值将被丢弃。

下面将举例说明用两种不同的脚本语言（VBScript 和 JScript）创建和调用过程。

<%@ LANGUAGE = VBSCRIPT >%
<HTML>
<BODY>
<% Call Echo %>
<BR>
<% Call PrintDate() %>
</BODY>
</HTML>

<%
Sub Echo
  Response.Write "<TABLE>"
  Response.Write "<TR><TH>Name</TH><TH>Value</TH></TR>"
  Set Params = Request.QueryString
  For Each p in Params
    Response.Write "<TR><TD>" & p & "</TD><TD>" & _
    Params(p) & "</TD></TR>"
  Next
Response.Write "</TABLE>"
End Sub
%>

<SCRIPT LANGUAGE=JScript RUNAT=Server>
function PrintDate()
{
  var x
  x = new Date()
  Response.Write(x.toString())
}
</SCRIPT>

将数组传递给过程

在 VBScript 中，要将一个完整的数组传递给过程，可使用数组名，后接空括号；而在 JScript 中，要用空的方括号。


使用组件和对象

ActiveX 组件是建立强大的 Web 应用程序的关键。组件提供了用在脚本中执行任务的对象。ASP 同样提供了可在脚本中使用的内建对象。本主题将讨论如何使用组件提供的对象以及由 Active Server Pages 直接提供的内建对象。

关于组件

ActiveX 组件是一个文件，该文件包含执行某项或一组任务的代码。组件可以执行公用任务，这样就不必自己去创建执行这些任务的代码。例如，股票行情收报机组件可以在 Web 页上显示最新的股票报价。ASP 带有可以直接使用的组件，如 Database Access 组件。从第三方开发者处获得可以可选的组件。或者也可以编写自己的组件。

可以利用组件作为脚本和基于 Web 应用程序的基本构造块。只要知道如何访问组件提供的对象。即使是位编写脚本的新手，也可以在不了解组件运作方式的情况下编写脚本。总之，组件使您不用学习编程就能够编写强大的脚本。

如果您是位 Web 应用程序的开发者，可以通过编写组件封装商务逻辑。例如，可以编写组件来计算产品的销售税。然后可以在处理销售订单的脚本中调用这个组件。在订单的处理过程中独立计算税率可以在某地销售税改变的时候只更新组件，而无须更改整个处理过程。可以使用任何支持组件对象模型 (COM) 的语言来编写组件，如，C、C++、Java 或 Visual Basic。如果熟悉 COM 编程，ActiveX 组件就是 Automation 服务器。要在 Web 服务器上运行，ActiveX 组件不能有图形用户接口元素，如 Visual Basic 的 MsgBox 函数。

组件是可以重复使用的。在 Web 服务器上安装了组件后，就可以从 ASP 脚本、ISAPI 应用程序、服务器上的其他组件或由另一种 COM 兼容语言编写的程序中调用该组件。

生成组件对象的实例

组件是包含在动态链接库 (.dll) 或可执行文件 (.exe) 中的可执行代码。组件可以提供一个或多个对象以及对象的方法和属性。要使用组件提供的对象，请创建对象的实例并将这个新的实例分配变量名。使用 ASP 的 Server.CreateObject 方法可以创建对象的实例。接着，使用脚本语言的变量分配指令为对象实例命名。创建对象实例时，必须提供实例的注册名称 (PROGID)。对于由 ASP 提供的基本组件，可以从参考页中获得对象的 PROGID。

例如，ASP 的 Ad Rotator 组件在图形广告中任意循环。Ad Rotator 组件提供了一个被称为 Ad Rotator 对象，该对象的 PROGID 是 "MSWC.AdRotator"。要创建一个 Ad Rotator 对象的实例，请使用下列指令：

VBScript：

<% Set MyAds = Server.CreateObject("MSWC.AdRotator") %>

JScript：

<% var MyAds = Server.CreateObject("MSWC.AdRotator") %>

如果您已经非常熟悉 VBScript 或者 JScript ，将会注意到没有使用创建新对象实例的脚本语言函数，如 VBScript 中的 CreateObject 或 JScript 中的 New。您必须使用 ASP 的 Server.CreateObject 方法，否者 ASP 无法跟踪脚本语言中对象的使用。

使用 HTML <OBJECT> 标签同样可以创建对象实例。您必须为 RUNAT 属性提供服务器值，同时也要为将在脚本语言中使用的变量名提供 ID 属性组。使用注册名 (PROGID) 或注册号码 (CLSID) 可以识别该对象。下面的例子使用注册名 (PROGID) 创建 Ad Rotator 对象的实例：

<OBJECT RUNAT=Server ID=MyAd PROGID="MSWC.AdRotator"></OBJECT>

下面的例子使用注册号码 (CLSID) 创建 Ad Rotator 对象的实例：

<OBJECT RUNAT=Server  ID=MyAd
CLASSID="Clsid:1621F7C0-60AC-11CF-9427-444553540000"></OBJECT>

从 Java 类中创建一个对象

使用 Java 语言编写的 ActiveX 组件可作为 Java 类而不是 DLL 提交。要使用 Server.CreateObject 创建 Java 类对象的实例，必须使用 Javareg 程序将该类注册为 COM 组件。然后就能够以 PROGID 或 CLSID 使用 Server.CreateObject 了。

如果对象实例不需要访问 ASP 内建对象和参与事务，就可以使用由 Java 监视程序提供的更为简单的机制直接调用 Java 类。必须用 Microsoft virtual machine for Java 2.0（由该 Internet Information Server 和 Personal Web Server 的发布版提供）使用 Java 监视程序。

如果要使用监视程序实例化对象，就必须使用 VBScript 或者 JScript 的 GetObject 指令并以 java:classname 的形式提供 java 类的全名。下面这个关于 VBScript 的例子生成了 Java Date 对象的实例。

<%
Dim date
Set date = GetObject("java:java.util.Date")
%>

<p> The date is <%= date.toString() %>

通过调用 GetObject 而不是 Server.CreateObject 生成的对象不能访问 ASP 内建对象也不能参与事务处理。

使用 ASP 内建对象

ASP 提供执行任务的内建对象。例如，Request 对象存储从 HTML 表格参考。

调用 Object 方法

方法是可以在对象上所执行或使用对象执行的活动。调用方法的一般语法为：

Object.Method parameters

参数随着方法的不同而不同。

例如，可以按照下列的指令，使用 Response 内建对象的 Write 方法将信息发送到浏览器：

<% Response.Write "Hello World" %>

注意 一些脚本语言不支持 Object.Method语法。如果使用的语言不支持该语法，那么为了将该语言作为主脚本语言，就必须在注册表中加入条目。

设置对象属性

属性是描绘对象的特征值。属性定义对象的特征（如对象类型）或对象的状态（如启用或禁用）。常规语法为：

Object.Property

可以读取并设置属性值。对某些对象，还可以添加新属性。

例如，Ad Rotator 组件有 Border 属性，该属性指定广告是否有边框及边框的粗细。下面的表达式指明没有边框：

<% MyAds.Border = 0 %>

可以使用 ASP 输出指令显示某些属性的当前值。例如，如果浏览器仍然与服务器连接，下面的命令将返回 TRUE：

<%= Response.IsClientConnected %>


使用集合

大多数 ASP 内建对象支持集合。集合是存储字符串、数字、对象和其他值的地方。除了在存储或取出项目时集合会自动扩展与搜索外，集合与数组非常相近。与数组不同的是，集合被修改后，项目的位置将会移动。可以通过集合中项目的名称、索引或者通过在集合的所有项目中遍历访问项目。

通过名称和索引访问项目

通过使用项目名称可以访问集合中的具体项目。例如，Contents 集合拥有在 Session 对象中保存的所有变量。同样也拥有由 Server.CreateObject 创建的所有对象。假设在 Session 对象中存储了下列用户信息：

<%
Session.Contents("FirstName") = "Sam"
Session.Contents("LastName") = "Woo"
Session.Contents("Age") = 29
%>

可以使用在集合中存储项目时关联的名称访问项目。例如，下面的表达式返回字符串“Sam”：

<%= Session.Contents("FirstName") %>

通过使用与项目关联的索引或号码也可以访问项目。例如，下面的表达式检索存储在 Session 对象的第二个存储槽中的信息并且返回“Woo”：

<%= Session.Contents(2) %>

ASP 集合从 1 开始编号。当在集合中增加或删除项目时，与项目关联的索引将会改变。所以不能认为项目的索引始终不变。正如将在下面的主题中说明的那样，利用索引的访问一般用来遍历集合，或访问只读集合中的项目。

通过使用速记的名称可以访问项目。ASP 以特定的顺序搜索与对象关联的集合。如果在对象的集合中特定名称的项目只出现一次的话，可以消除该集合的名称：

<%= Session("FirstName") %>

访问存储在 Application 或 Session 对象中的项目时，消除集合名称一般是安全的。但是，对于 Request 对象，最好指定集合名称，因为该集合很可能包含重复的名称。

遍历集合

在集合的所有项目中遍历可以了解集合中存储的项目或修改项目。遍历集合时，必须提供集合名称。例如，可以使用 VBScript 中的 For...Each 语句访问存储在 Session 对象中的项目：

<%
'Declare a counter variable.
Dim Item

'For each item in the collection, display its value.
For Each Item in Session.Contents
  Response.Write Session.Contents(Item) & "<BR>"
Next
%>

可以使用 VBScript 中的 For...Next 语句遍历集合。例如，要列出上例中存储在 Session 中的三个项目，可以使用下列语句。

<%
'Declare a counter variable.
Dim Item

'Repeat the loop until the value of counter is equal to 3.
For Item = 1 to 3
  Response.Write Session.Contents(Item) & "<BR>"
Next
%>

因为一般不知道存储在集合中的项目个数，ASP 支持集合的 Count 属性，这个属性返回集合中的项目数。可以使用 Count 属性指定计数器的终值。

<%
'Declare a counter variable.
Dim Item

'Repeat this loop until the counter equals the number of items
'in the collection.
For Item = 1 to Session.Contents.Count
   Response.Write Session.Contents(Item) & "<BR>"
Next
%>

可以在脚本中使用 for 语句在集合中循环。在 JScript 的 for 语句中使用 Count 属性时，为了收到更大的效果，应该将 Count 值分配给本地变量并使用该变量设置计数器终值。这样，脚本引擎就不需要每次循环都查寻 Count 的值。下面的例子展示了这个技巧：

<%
var item, numitems;
numitems = Session.Contents.Count;
for (item = 1; item <= numitems; item++) {
  Response.Write(Session.Contents(item) + "<BR>")
}
%>

Microsoft JScript 3.0 引入了 Enumerator 对象。可以使用该对象遍历 ASP 集合。atEnd 方法指出了集合中是否还存在项目。moveNext 方法移动到集合中的下一个项目。

<%
// Create an Enumerator object
var mycoll = new Enumerator(Session.Contents);

//Iterate through the collection and display each item
while (!mycoll.atEnd()) {
  var x  = mycoll.item();
  Response.Write(Session.Contents(x) + "<BR>");
  mycoll.moveNext();
}
%>

遍历带子关键字 (Subkeys) 的集合

脚本在单一 cookie 中嵌入相关值以减少在浏览器和 Web 服务器之间传送的 cookie 数目。因此 Request 和 Response 对象的 Cookies 集合能够在单一项目中拥有多个值。这些子项目或子关键字可以被单个访问。只有 Request.Cookies 和 Response.Cookies 集合支持子关键字 (Subkeys)。Request.Cookies 只支持读操作；Response.Cookies 只支持写操作。

可以列举 Request.Cookie 集合中所有的 cookie 以及 Cookie 中所有的子关键字 (Subkeys)。但是，如果在没有子关键字 (Subkeys) 的 Cookie 上遍历子关键字，将不会产生任何结果。通过使用 .HasKeys 语法首先检查 cookie 是否含有子关键字 (Subkeys)，就可以避免这种情况。下面的这个例子展示了这个技巧。

<%
'Declare counter variables
Dim Cookie, Subkey

'Display the entire cookie collection.
For Each Cookie in Request.Cookies
  Response.Write Cookie & "<BR>"
    If Request.Cookies(Cookie).HasKeys Then
      'Display the subkeys
      For Each Subkey in Request.Cookies(Cookie)
    Response.Write Subkey & "=" & Request.Cookies(Cookie)(Subkey) & "<BR>"
      Next
    Else
      Response.Write "No subkeys in this cookie <BR>"
    End If
Next
%>

遍历对象集合

Session 和 Application 集合可以保存数量变量或者对象实例。Contents 集合拥有数量变量和通过调用 Server.CreateObject 生成的对象实例。StaticObjects 集合拥有在 Global.asa 文件中使用 HTML <OBJECT> 元素创建的对象。

在遍历包含对象的集合时，可以访问对象的标识符或对象的方法和属性。例如，假设应用程序使用一些对象创建用户帐号，而且每个对象有初始化方法，可以遍历 StaticObjects 集合来调用每个初始化方法：

<%
For Each Object in Session.StaticObjects
  Session.StaticObjects(Object).InitializeUser
Next
%>

ASP 集合有何不同之处？

尽管在本主题中讨论的 ASP 集合与 Visual Basic 的 Collection 对象非常相似，但还是有些不同。ASP 集合支持 Count 属性和 Item 方法，但不支持 Add 和 Remove 方法。


设置对象作用域

对象的作用域决定哪些脚本可以使用该对象。默认情况下，当您创建对象实例时，该对象具有页作用域。同一 ASP 页中的任何脚本命令都能使用该页作用域的对象；当 ASP 页送回客户端时，该对象即被释放。对大多数对象来说，推荐的作用域是页作用域。您可以改变一个对象的作用域，使其可被其他页的脚本使用。本主题将解释如何使用页作用域的对象以及如何改变对象的作用域。

使用页作用域对象

在 ASP 页上用 Server.CreateObject 创建的对象在该页的生存期内一直存在。该对象对该页的任何脚本命令都是可访问的，当 ASP 处理完该页时，该对象即被释放。因此，对象具有该页的作用域或生命周期。

在用 Visual Basic 或 VBScript 编程时，要注意在 ASP 处理完该页之前不要释放对象。例如，以下语句经常用于通过将对象变量赋以 Nothing 值来释放对象：

Set myObj = Nothing

如果您在 ASP 页中包含了该语句，那么任何使用 myObj 的企图都将会返回一个预期的错误代码。但在内部，即使在对象释放以后，ASP 仍保留对它的引用。当您在脚本中不能使用对象时，对象的资源直到 ASP 处理完页之后才释放。同样，如果您通过创建另一个对象实例并将其赋给已使用过的对象变量来释放该对象时，ASP 将保留对原对象实例的引用。对大多数脚本来说，创建多个对象可能不会产生问题，但如果对象使用共享资源，比如数据库连接，就有可能出现问题。

由于对象有页作用域，所以不要依靠手工释放的对象。例如，以下的循环创建 1001 个 Connection 对象，它将能打开大多数的连接甚至于一个大型的 SQL server：

<%
For I = 0 to 1000
  Set Conn = Server.CreateObject("ADODB.Connection")
  Conn.Open "connection string"
Next
%>

总的来说，应该尽量避免在一个循环内部创建对象。如果无法避免，您应该手工释放被对象使用过的资源。如果 Connection 对象仅被创建一次，且数据资源的物理连接在每个循环中被打开然后关闭，那么上例将会正常运行：

<%
Set Conn = Server.CreateObject("ADODB.Connection")
For I = 0 to 1000
  Conn.Open "connection string"
  Conn.Close
Next
%>

为对象赋予会话作用域

在应用程序中，对于每个新会话，都会创建 session-scope 对象，并且在会话结束后会将其释放。因此，每个活动的会话都有一个对象。会话作用域用于从多个脚本中调用的对象，但只影响一个用户会话。您可以只在需要时才为对象赋予会话作用域。如果确实需要使用会话作用域，那么就必须了解提供对象的组件的线程模型，因为它影响性能和对象的安全环境。详细信息，请参阅本主题的“高级信息：性能问题” 。

要为对象赋予会话作用域，请将对象存储在 ASP Session 内建对象中，您既可以在 Global.asa 文件中使用 <OBJECT> 标记，也可以在 ASP 页上使用 Server.CreateObject 方法创建具有会话作用域的对象实例。

在 Global.asa 文件中，您可用扩展了 RUNAT 属性（必须设置为 Sever）和 SCOPE 属性（必须设置为 Session）的 ;OBJECT> 标记。以下示例创建一个 Ad Rotator 对象的会话作用域实例：

<OBJECT RUNAT=Server SCOPE=Session ID=MyAd PROGID="MSWC.Adrotator">
</OBJECT>

一旦您在 Session 对象中存储了对象，您就可以从应用程序的任何页中访问该对象。下面的语句使用上例中由 <OBJECT> 标记创建的对象实例：

<%= MyAd.GetAdvertisement("addata.txt") %>

在 ASP 页上，您也可以使用 Server.CreateObject 方法将对象存储在 Session 内建对象中。以下示例在 Session 对象中存储 Ad Rotator 对象的一个实例。

<% Set Session("MyAd") = Server.CreateObject("MSWC.Adrotator") %>

要显示广告，您首先应该获取存储在 Session 对象中的 Ad Rotator 对象的实例，然后才能调用方法来显示对象：

<% Set MyAd = Session("MyAd") %>
<%= MyAd.GetAdvertisement("addata.txt") %>

在用 <OBJECT> 标记声明的对象被某个 .asp 文件中的脚本命令引用之前，ASP 并不创建其实例。Server.CreateObject 方法则立即创建该对象实例。因此，对会话作用域对象来说，使用 <OBJECT> 标记要比 Server.CreateObject 属性更好。

为对象赋予应用程序作用域

application-scope 对象是在应用程序启动时就创建的对象的单个实例。该对象由所有客户端请求共享。仅在极少数情况下，您才需要为对象赋予应用程序作用域。一些实用程序对象，例如计数器等，可能需要应用程序作用域。但一般来说，您可用在下一节中建议的替代方案。另外，线程模型会影响性能和对象安全环境（请参阅本主题的“高级信息：性能问题”）。

要为对象赋予应用程序作用域并将其存储在 ASP Application 内建对象中，既可以使用 Global.asa 文件中的 <OBJECT> 标记，也可以使用 ASP 页上的 Server.CreateObject 方法创建应用程序作用域的对象实例。

在 Global.asa 文件中，您可用扩展了 RUNAT 属性（必须设置为 Sever）和 SCOPE 属性（必须设置为 Session）的 ;OBJECT> 标记。在 ASP 页中，您可以使用 Server.CreateObject 将对象实例存储在 Application 内建对象中。关于使用 <OBJECT> 标记和 Server.CreateObject 的示例，请参阅上一节“为对象赋予会话作用域”。

会话和应用程序作用域的替代方案

仅当需要时，才能为对象赋予会话或应用程序作用域。因为在会话或应用程序结束运行之前，这些对象会一直保留。它们会占用内存或数据库连接等资源，这些资源可能会在其他方面更有用。另外，组件的线程模型会影响您从中所创建的对象的性能，尤其是那些具有会话或应用程序作用域的对象。

在很多情况下，比创建应用程序或会话作用域对象更好的方法就是利用会话或应用程序作用域变量，将信息传递给在网页一级创建的对象。例如，不要为 ADO Connection 对象赋予会话或应用程序作用域，因为它创建的连接会在相当长的一段时间一直保持打开而此时脚本已不再使用 ODBC 连接共享。但您可以将 ODBC 连接字符串存储在 Session 或 Application 内建对象中，并在网页上从创建的 Connection 对象实例中获取该字符串。通过这种方式，您可以存储在会话或应用程序名称空间中频繁使用的信息，但只有在需要时才创建用该信息的对象。关于作用域变量的详细信息，请参阅“使用变量和常量”。

用户自定义的 JScript 对象

您可以通过定义一个创建和初始化新对象的属性和方法的构造函数来创建自己的 JScript 对象。当脚本用 new 操作符来调用构造函数时，就会创建该对象的实例。ASP 脚本支持用户自定义的对象，当具有页作用域时，后者正常运行。但如果为用户自定义的 JScript 对象赋予应用程序或会话作用域，将可能影响该对象的功能。特别是，若一个对象具有会话或应用程序作用域，则其他页的脚本可以获取该对象的属性，但是却不能调用其方法。

高级信息：性能问题

组件的线程模型可能会影响 Web 站点的性能，一般来说，带有 Both 标记的对象是推荐在所有的 ASP 脚本中使用的对象，尤其是在 Session 和 Application 对象中。不推荐使用单线程对象。

因为您可能不会始终控制所用对象的线程模型，所以，以下的指导可帮助您获得最佳性能：

  • 页作用域对象。带有 Both 或 Apartment 标记的对象将给予您最佳的性能。
  • 应用程序作用域对象。一般来说，应避免在 Application 对象中放置对象。如果确需使用应用程序作用域对象，您会从结合了 FreeThreadedMarshaler 的带有 Both 标记的对象中获得最佳性能。您既可以用 <OBJECT> 标记也可以用 Server.CreateObject 方法在 Application 对象中存储带有 Single、Free 或 Both 标记的对象。您必须用单元线程对象来使用 <OBJECT> 标记。
  • 会话作用域对象。带有 Both 标记的对象将为您提供最佳性能。用单线程或单元线程对象会导致 Web 服务器将会话锁定在一个线程上。自由线程对象不会锁定会话，但运行速度不高。在 Session 对象中，您可以用 <OBJECT> 标记或 Server.CreateObject 方法存储对象 。

如果您已安装了 SDK 文档，您将会获得有关线程模型及其隐含的组件性能的详细信息。（在 Windows 95 及其后续版本中 SDK 文档不可用。）


ASP 内建对象

Active Server Pages 提供内建对象，这些对象使用户更容易收集通过浏览器请求发送的信息、响应浏览器以及存储用户信息（如用户首选项）。本文简要说明每一个对象。

Application 对象

可以使用 Application 对象使给定应用程序的所有用户共享信息。

Request 对象

可以使用 Request 对象访问任何用 HTTP 请求传递的信息，包括从 HTML 表格用 POST 方法或 GET 方法传递的参数、cookie 和用户认证。Request 对象使您能够访问发送给服务器的二进制数据，如上载的文件。

Response 对象

可以使用 Response 对象控制发送给用户的信息。包括直接发送信息给浏览器、重定向浏览器到另一个 URL 或设置 cookie 的值。

Server 对象

Server 对象提供对服务器上的方法和属性进行的访问。最常用的方法是创建 ActiveX 组件的实例 (Server.CreateObject)。其他方法用于将 URL 或 HTML 编码成字符串，将虚拟路径映射到物理路径以及设置脚本的超时期限。

Session 对象

可以使用 Session 对象存储特定的用户会话所需的信息。当用户在应用程序的页之间跳转时，存储在 Session 对象中的变量不会清除；而用户在应用程序中访问页时，这些变量始终存在。也可以使用 Session 方法显式地结束一个会话和设置空闲会话的超时期限。

ObjectContext 对象

可以使用 ObjectContext 对象提交或撤消由 ASP 脚本初始化的事务。


ASP 内建对象速查卡

Application 对象
集合：
Contents
StaticObjects
方法：
Lock
Unlock
事件：
Application_OnEnd
Application_OnStart

ObjectContext 对象
方法：
SetAbort
SetComplete
事件：
OnTransactionAbort
OnTransactionCommit

Request 对象
集合：
ClientCertificate
Cookies
Form
QueryString
ServerVariables
属性：
TotalBytes
方法：
BinaryRead
Response 对象
集合：
Cookies
属性：
Buffer
CacheControl
Charset
ContentType
Expires
ExpiresAsolute
IsClientConnected
PICS
Status
方法：
AddHeader
AppendToLog
BinaryWrite
Clear
End
Flush
Redirect
Write

Server 对象
属性：
ScriptTimeout
方法：
CreateObject
HTMLEncode
MapPath
URLEncode

Session 对象
集合：
Contents
StaticObjects
属性：
CodePage
LCID
SessionID
Timeout
方法：
Abandon
事件:
Session_OnEnd
Session_OnStart


ActiveX 组件

本部分概述了 Active Server Pages（ASP）中的 ActiveX 组件。

ActiveX 组件作为基于 Web 的应用程序部分在 Web 服务器上运行。组件提供了应用程序的主要功能（如访问数据库），这样就不必创建或重新创建执行这些任务的代码。

数据库访问

可以使用 Database Access 组件在应用程序中访问数据库。然后可以显示表的整个内容、允许用户构造查询以及在 Web 页执行其他一些数据库查询。

Ad Rotator

可以使用 Ad Rotator 组件来交替显示图像，并提供从显示的图形到另一个 URL 的链接。在文本文件中保存广告列表；Ad Rotator 组件依照在数据文件中的指令来显示它们。

Content Rotator

Content Rotator 组件在 Web 页上自动循环 HTML 内容字符串。每次用户请求 Web 页时，Content Rotator 组件基于 Content Schedule 文件中指定的信息显示新的 HTML 内容字符串。

由于内容字符串可以包含 HTML 标记，就可以显示 HTML 能够表示的任何内容类型：文本、图形或超文本链接。例如，可以使用该组件在每日牌价或超文本链接中循环，或者在每次打开 Web 页时，改变文本和背景的颜色。

Browser Capabilities

通过使用 Browser Capabilities 组件，可以基于浏览器的功能剪裁发送到该浏览器的内容。

File Access

File Access 组件提供可用于在计算机文件系统中检索和修改文件的对象。

Content Linking

Content Linking 组件使在应用程序中提供 .asp 文件的逻辑导航变得简单易行。不用在许多 .asp 文件中维护 URL 引用，而只需在易于编辑的文本文件中指定 .asp 文件的次序组织。

Collaboration Data Objects for Windows NT Server

Collaboration Data Objects for NTS 组件提供 Web 应用程序所使用的邮件对象。这个库使您能够简单快捷地在应用程序上添加收发邮件的功能。您可以创建可编程邮件对象，然后利用它们的属性和方法来满足应用程序的需要。

MyInfo、Status、System 和 Tools

MyInfo、Status、System 和 Tools 组件为在 Macintosh 上和在运行 Microsoft Windows 的计算机上开发的应用程序提供兼容性。

  • MyInfo 组件跟踪 Web 站点所有者的个人信息，如经营 Web 站点的组织名称和地址及 Web 站点的设置，还有 Web 站点是否有 guest book。
  • Status 组件跟踪 Web 站点的信息，如访问者的数量以及 HTTP 连接的个数。
  • System 组件创建包含服务器状态信息的 status 对象。当前该服务器状态只在 Personal Web Server for Macintosh 上可用。
  • Tools 组件提供了生成随机数、检查文件是否存在或处理 HTML 表格的方法。

Page Counter

Page Counter 组件统计并显示 Web 页被请求的次数。以一定的时间间隔，将捕获的数字写入到文本文件中，这样服务器关闭后，数据也不会丢失。

Permission Checker

Permission Checker 组件测试 Web 用户对某文件或某页的访问权。可以使用 Permission Checker 组件为不同类型的用户定制基于 ASP 的页。例如，如果 Web 页包含超文本链接，就可以使用 Permission Checker 组件测试用户对相应 Web 页的访问权限并忽略用户无权访问的页或使这些链接失效。


编写简单脚本

一个 ASP 脚本能执行的任务从简单如显示一个变量的值到复杂如发送一条 SQL 语句给数据库。本节讨论许多脚本编写人员想完成的通用任务，例如处理一个 HTML 表格返回的信息或调试一个脚本。如果您是脚本语言的新手或只是 ASP 的新手，请认真阅读 使用脚本语言 中的主题来学习如何创建一个 ASP 页以及 ASP 命令的基本语法。

本节包括：

  • 发送内容给浏览器：解释如何控制返回给浏览器的页。
  • 发送脚本给浏览器：解释如何使用服务器脚本创建客户端脚本。
  • 包含文件：解释如何使用 #include 语句将一个文件的内容插入到 ASP 文件中去。
  • 处理 HTML 表格：解释如何从 HTML 表格中获取数据。
  • 访问数据库：解释如何用 Database Access 组件从数据库中检索信息。
  • 调试 ASP 脚本：解释在脚本中如何用交互式调试工具查找和消除错误。
  • 解释 ASP 错误信息：描述常见的 ASP 错误的原因。

本节不包括下列信息：

  • 创建 ASP 页和使用 ASP 命令的基本信息。
  • 更高级的任务。
  • ASP 对象和组件的参考页。


向浏览器发送内容

在处理 ASP 脚本时，任何没有包含在 ASP 定界符或 <SCRIPT> 标记中的文本或图形都将被简单地返回给浏览器。可以通过使用 Response 对象显示地把内容发送给浏览器。

发送内容

要将内容从 ASP 定界符内部或过程发送给浏览器，可以使用 Response 对象的 Write 方法。例如，下面的语句可以根据用户是否访问过此页而发送不同的问候语：

<%
If FirstTime = True Then
  Response.Write "<H3 ALIGN=CENTER>Welcome to the Overview Page</H3>"
Else
  Response.Write "<H3 ALIGN=CENTER>Welcome Back to the Overview Page</H3>"
End If
%>

在过程外部，不必使用 Response.Write 将内容送回用户。不在脚本定界符内部的内容被直接发送给浏览器，浏览器将其格式化和显示。例如，下面的脚本过程与上面的脚本输出相同：

<H3 ALIGN=CENTER>
<% If FirstTime Then %>
Welcome to the Overview Page.
<% Else %>
Welcome Back to the Overview Page.
<% End If %>
</H3>

当您只需要将输出返回一次或很方便地向现有 HTML 文本中加入语句时，可使用混合脚本命令和 HTML。当您不想用定界符分隔一条语句或当您想创建返回给浏览器的字符串时，可使用 Response.Write。例如，可构建一个文本的字符串，用从一个 HTML 表送回的值创建表格的一行：

Response.Write "<TR><TD>" & Request.Form("FirstName") _
 & "</TD><TD>" & Request.Form("LastName") & "</TD></TR>"

Request.Form 返回从 HTML 表格（参阅 使用 HTML 表格）发送的值。(&) 字符是 VBScript 字符串连接字符。

设置内容的类型

当 Web 服务器将文件返回给浏览器时，会同时告诉浏览器文件中包含的内容的类型。这使浏览器能够决定是否它能自己显示文件或必须调用另一个应用程序。例如，如果网络服务器返回 Microsoft Excel 表格，则浏览器必须调用 Microsoft Excel 的副本显示此页。Web 服务器通过将文件的扩展名映射到 MIME 类型表来识别文件类型。

可以使用 Response 对象的 ContentType 属性为发送给用户的内容设置 HTTP 内容类型字符串。例如，下面的命令为通道定义设置内容类型：

<% Response.ContentType = "application/x-cdf" %>

有关通道的详细信息，请参阅本主题中的“创建动态通道”。

其他的通用内容类型是 text/plain（用于作为文本内容返回而不是已解释的 HTML 语句）、text/gif（用于 GIF 图像）和 video/quicktime（用于 Apple QuickTime® 格式的电影）。一套标准的 MIME 类型已经定义，另外，Web 服务器或 Web 浏览器都支持 MIME 类型。要想查看您的 Microsoft Web 服务器支持哪些内容类型，可使用 Internet 服务管理器打开您的 Web 站点的属性页，单击“HTTP 标题”选项卡，然后单击“文件类型”选项卡。

重定向浏览器

用 Redirect 方法可将浏览器重定向到另一个 URL，而不是将内容发送给用户。例如，如果您想确认用户是否已从主页进入了您的应用程序，以便能收到一个客户 ID，则可以检验他们是否有客户 ID 号；如果没有，就可以将其重定向到主页。

<%
If Session("CustomerID") = 0 Then
  Response.Redirect "homepage.asp"
End If
%>

除非缓冲区已经打开，否则，在任何内容或标题返回给浏览器之前，您必须重定向浏览器。将 Response.Redirect 语句放在页的顶部和<HTML> 标记之前可确保没有任何内容返回给浏览器。如果在返回给浏览器的内容或标题后使用 Response.Redirect，将看到一个错误信息。

如果在页的中间使用 Response.Redirect，请将其与 Response.Buffer 属性一起使用，下面的部分将进行解释。

缓冲内容

默认情况下，Web 服务器返回 HTML 和在处理 ASP 页时的脚本处理结果。但是，您可以设置 Response 对象的 Buffer 属性以便在向用户发送任何内容之前，先处理页上的所有的服务器脚本命令。

可以使用缓冲技术来确定在页处理过程中的某个点，而您并不想将该点之前的内容发送给用户。也可以用 Response 对象的 Redirect 方法将用户重定向到另一页，或者用 Response 对象的 Clear 方法清除缓冲区并将不同的内容发送给用户。下面的例子使用了以上两种方法。

<%
'Turn on buffering.  This statement must appear before the <HTML> tag.
Response.Buffer = True %>
<html>
<body>
.
.
.
<%
If Request("FName") = "" Then
  Response.Clear
  Response.Redirect "/samples/test.html"
Else
  Response.Write Request("FName")
End If
%>
</body>
</html>

也可以使用 Response.Buffer 避免 Web 服务器在脚本修改 HTTP 标题之前将其返回。有些属性和方法，例如 Response.Expires 和 Response.Redirect 可修改 HTTP 标题。

当在脚本中设置 Buffer 属性并且没有调用 Flush 方法时，服务器将保持用户发出的 Keep-Alive 请求。养成这样的脚本编写习惯有益于提高服务器的性能，因为，服务器不必为每一个用户请求创建新的连接（假定服务器、用户和任何代理服务器都支持 Keep-Alive 要求）。但是，这种方法的一个潜在的不利因素是：在用户处理完当前的 asp 文件的所有的脚本之前，缓冲区不显示任何响应给用户。对于较长的和较复杂的脚本，用户可能要被迫等待很长一段时间才能看到这一页。

默认情况下，缓冲区对于 ASP 应用程序是关闭的。可以使用 Internet 服务管理器为整个 ASP 应用程序打开缓冲区。

允许代理服务器缓存页

通过代理服务器，应用程序可以发送页给用户。代理服务器代替用户浏览器从 Web 站点请求网页。代理服务器缓存 HTML 页以便相同页的重复请求能够快速有效地返回给浏览器。代理服务器执行请求并缓存网页，并减轻网络和 Web 服务器的负荷。

尽管缓存对 HTML 页都能很好运行，但对包含动态生成信息的 ASP 页则不尽人意。例如，报告股市行情或显示大量业务的存货清单需要提供即时信息。一小时前的信息对目前来讲是很不准确的。如果应用程序返回个人的信息，例如，自定义的主页，希望用户不能看到另一个用户的个人信息。

默认情况下，ASP 命令代理服务器自己不能缓存 ASP 页（尽管缓存图像、位图、小型应用程序，和其他缓存页上的参考项）。可以使用 Response.CacheControl 属性设置缓存控制 HTTP 标题字段允许缓存某一页。Response.CacheControl 的默认值是字符串 "Private"，它避免代理服务器缓存此页。要允许缓存，可将缓存控制标题字段设置为 Public：

<% Response.CacheControl = "Public" %>

因为在任何页的内容被发送之前，HTTP 标题必须被送给浏览器或代理服务器，所以，可在任何 HTML 标记之前设置 Response.CacheControl 属性或使用 Response.Buffer 缓存此页。

缓存控制标题字段是 HTTP 1.1 规格的一部分。在只支持 HTTP 1.0 的代理服务器上不能缓存 ASP 页，因为没有到期的标题字段发送。

避免浏览器缓存页

每一个浏览器版本都有它自己的规格来规定是否缓存页。要避免浏览器缓存 ASP 页，可使用 Response.Expires 设置到期标题：

<% Response.Expires = 0 %>

值为 0 强迫缓存页到期。因为在任何页被发送之前，HTTP 标题必须被送给浏览器，所以可通过将 Response.Expires 属性放在 HTML 标记之前或使用 Response.Buffer 缓存该页。

创建动态通道

Internet Explorer 4.0 有一个新的特性，Web 规划人员可以使用该属性将带有公用主题的 Web 页并入一个通道。在浏览器中，通道被显示在通道标题栏上；用户通过单击图标访问通道。通道在后台自动更新；用户不必访问站点就可以在自己的浏览器上下载最新的页。通道为用户提供了一条浏览一组相关的 Web 页的快速而直接的通路，并且这些 Web 页是自动更新的。

使用 ASP，可以编写脚本来收集用户的首选项，然后动态地创建通道。通道定义文件 (.cdf) 建立了通道内容的组织和顺序。在 .cdf 文件中的命令使用与 HTML 标记相同的语法，以便于掌握和从脚本中生成。在编写 ASP 脚本来创建通道定义文件时，脚本用 .cdx 扩展名。当 ASP 读取一个以 .cdx 为扩展名的文件时，将自动发送 application/x-cdf 内容类型，它告诉浏览器用通道定义来解释字节。如果不使用 .cdx 作扩展名，则脚本必须用 Response.ContentType 手工将内容类型设置为 application/x-cdf。

下面是一个有关如何使用通道的示例。下面的 HTML 表格要求用户选择通道。提交时，该表格调用 .cdx 文件的脚本去创建通道的定义。

<P> Choose the channels you want. </P>
<FORM METHOD="POST" ACTION="chan.cdx">
<P><INPUT TYPE=CHECKBOX NAME=Movies> Movies
<P><INPUT TYPE=CHECKBOX NAME=Sports> Sports
<P><INPUT TYPE="SUBMIT" VALUE="SUBMIT">
</FORM>

Chan.cdx 中的脚本根据与请求一起提交的表格的值创建通道定义。

<% If Request.Form("Movies") <> "" Then %>
  <CHANNEL>
    channel definition statements for the movie pages
  </CHANNEL>
<% End If %>

<% If Request.Form("Sports") <> "" Then %>
  <CHANNEL>
    channel definition statements for the sports pages
  </CHANNEL>
<% End If %>

向服务器发送文件

浏览器可以使用 Posting Acceptor 应用程序将文件发送给 Web 服务器。当 Posting Acceptor 上载文件时，将发送列出每一个收到的文件名称和位置的 URL-encoded 表格字段。可以将邮递处理的 URL 添加到脚本中，此脚本上载文件去调用 ASP 脚本来处理这些字段名。例如，可以编写一个脚本，自动地通过文件的名称和位置发送 e-mail 给系统管理员。


向浏览器传送脚本

尽管 ASP 主要用来创建和处理服务器端脚本，还是可以使用它生成由客户浏览器处理的客户端脚本来扩展其效用。通过组合传送到浏览器的脚本命令可以编写服务器端脚本。

通过组合由 HTML 注释括起来的客户端脚本和由定界符括起来的服务器端脚本可以做到这一点：

<SCRIPT LANGUAGE="VBScript">
<!--
client script
<% server script  %>
client script
<% server script  %>
client script
...
-->
</SCRIPT>

使用脚本语言的这个功能，您能够创建令人兴奋的应用程序。举例来说，下面的脚本将生成在用户的 Web 浏览器上运行的客户脚本的子程序。

<%
ServerTime = Time
ServerDate = Date

For i = 1 to 4
  Randomize
  GreetCondition = int(rnd * 3)
%>

<SCRIPT LANGUAGE="VBScript">
<!--

Sub ServeInfo<%= i %>()
  Select Case <%= GreetCondition%>
    Case 0
      Msg =  "Hello, the time is <%= ServerTime %>."
    Case 1
      Msg = "Welcome! Today's date is <%= ServerDate %>."
    Case 2
      Msg = "Hi, the time is <%= ServerTime %> and the date is <%= ServerDate %>.
  End Select
  Document.Write    Msg
End Sub

ServeInfo<%= i %>()

//-->
</SCRIPT>

<br>

<%
Next
 %>

在以上的脚本中，ASP 在服务器上检索时间和日期信息，然后通过几次循环生成在用户的 Web 服务器上运行的子程序。每个客户端子程序提出随机选择的问候，显示时间和日期信息。

这种脚本可扩展，例如，将配置信息检索并提交到指定的客户端脚本或组件，如 ActiveX 控件。灵活地使用这种脚本的编写技巧，同样可以加快 Web 服务器处理和返回用户信息请求的速度。


包含文件

SSI 指令为用户提供在 Web 服务器处理之前将一个文件的内容插入到另一个文件的方法。ASP 只使用这一机制的 #include 指令。要在 .asp 文件中插入一个文件，使用下面的语法：

<!--#include virtual | file ="filename"-->

virtual 和 file 关键字指示用来包含该文件的路径的类型，filename 是您想包含的文件的路径和名称。

被包含文件不要求专门的文件扩展名；但是，为被包含文件赋予 .inc 扩展名以便和其他类型文件相区分是一个良好的编程习惯。

使用 Virtual 关键字

使用 Virtual 关键字指出路径开始于虚拟目录。例如，如果一个被命名为 Footer.inc 的文件属于一个名为 /Myapp 的虚拟目录，则下面的一行将把 Footer.inc 的内容插入到包含该行的文件中：

<!--#include virtual ="/myapp/footer.inc"-->

使用 File 关键字

使用 file 关键字指示使用相对路径。相对路径开始于含有该包含文件的目录。例如，如果您的文件位于目录 Myapp 中，而文件 Header1.inc 在 Myapp\Headers 中，下面的一行将把 Header1.inc 插入到您的文件中：

<!--#include file ="headers/header1.inc"-->

注意，到被包含文件 Headers/header1.inc 的路径是相对于包含文件的；如果包含 #include 语句的脚本不在 /Myapp 目录中，那么该语句将不起作用。

如果在 Internet 服务管理器中的“启用上层目录”选项被选中，则也可以使用 file 关键字和 ../ 语法包含父目录即上一层目录中的文件。

被包含文件的位置

被包含文件可以在您的 Web 站点内的某个目录中，也可以在您的 Web 站点之外。通常，您应该使被包含文件位于 Web 站点的目录中。如果一个被包含文件位于您的 Web 站点内，则当浏览器下次请求包含文件时，将显示对被包含文件的改变。但是，如果被包含文件位于您的 Web 站点之外，直到 ASP 应用程序重新启动或 Web 服务器重新启动时，这种改变才能体现出来。ASP 检测在应用程序命名空间中（在应用程序的起始目录下）的任何包含文件的改变。

包含文件：提示和警告

一个被包含文件也可以包含其他的文件。如果 #include 指令没有导致循环，一个 .asp 文件可以多次包括同一个文件。例如，如果文件 First.asp 包含文件 Second.inc，则 Second.inc 一定不能再包含 First.asp。一个文件也不能包含自身。ASP 检测此类循环或嵌套错误，并在检测到时产生一个错误消息，同时停止处理被请求的 .asp 文件。

ASP 在执行脚本命令之前包含文件。因此，不能用脚本命令去创建被包含文件的名称。例如，下面的脚本将不能打开 Header1.inc，因为 ASP 会在它分配一个文件名给变量 name 之前先执行 #include 指令。

<!-- This script will fail -->
<% name=(header1 & ".inc") %>
<!--#include file="<%= name %>"-->

脚本命令和过程必须完全包含在脚本定界符 <% 和 %> 、HTML 标记 <SCRIPT> 和 </SCRIPT> 或 HTML 标记 <OBJECT> 和 </OBJECT> 中。也就是说，不能在一个 .asp 包含文件中打开一个脚本定界符，然后在一个被包含的文件中才关闭该定界符；脚本或脚本命令必须是一个完整的单元。例如，下面的脚本将无法运行：

<!-- This script will fail -->
<%
For i = 1 To n
  statements in main file
  <!--#include file="header1.inc" -->
Next
%>

下面的脚本将正常运行：

<%
For i = 1 to n
  statements in main file
%>
<!--#include file="header1.inc" -->
<% Next %>


使用 HTML 表格

使用 ASP Request 对象，您可以创建一个简单而功能强大的脚本来收集和处理 HTML 表格数据。在本主题中，您将不仅学会如何创建基本的表格处理脚本，而且还将获得用于验证 Web 服务器和用户浏览器上的表格信息的一些有用技术。

关于 HTML 表格

HTML 表格是收集 Web 信息最常用的方法，是在 Web 页上提供用户界面控件的特殊的 HTML 标记的排列。文本框、按钮和复选框都是典型的控件，这些控件使用户和 Web 页实现交互，并且将信息提交给 Web 服务器。

下面的 HTML 示例产生一个表格，在表格中，用户可以输入姓名、年龄并包含一个将这些信息提交给 Web 服务器的按钮。该表格也包含了一个隐含的控件（Web 浏览器不显示），可以用该控件向 Web 浏览器传递附加信息。

<FORM METHOD="POST" ACTION="myfile.asp">
<INPUT TYPE="text" NAME="firstname">
<INPUT TYPE="text" NAME="lastname">
<INPUT TYPE="text" NAME="age">
<INPUT TYPE="hidden" NAME="userstatus" VALUE= "new">
<INPUT TYPE="submit"  VALUE="Enter">
</FORM>

处理 ASP 输入的表格

在表格向 Web 服务器提交信息时，用户的 Web 浏览器请求用 HTML <FORM > 标记的 ACTION 属性所指定的 .asp 文件（在前面的例子中，该文件被称为 Myfile.asp）。.asp 文件包含了处理表格值（如显示结果表或从数据库查询信息）的脚本。

可以通过三种途径用 .asp 文件收集 HTML 表格的值

  • 静态的 .htm 文件可以包含一个将其数值邮送给 .asp 文件的表格。
  • .asp 文件可以创建一个将其信息邮送给另一个 .asp 文件的表格。
  • .asp 文件可以创建一个将其信息邮送给自身的表格，即包含该表格的文件。

前两个方法的操作方式相同，当表格与网关程序交互时，除 ASP 之外，可以包含读取和响应用户选择的命令。

创建一个包含表格定义且传送信息给自身的 .asp 文件较复杂，但却是有很强功能的处理表格的方法。这一过程在 验证表格输入 中演示。

获得表格输入

ASP Request 对象提供了两种集合，在很大程度上简化了检索附加在 URL 请求上的表格信息的任务。

QueryString 集合

QueryString 集合获取作为跟在请求的 URL 的问号后面的文本传递给 Web 服务器的值。通过使用 HTTP GET 方法或手工将表格的值添加到 URL，表格的值可以被附加在请求的 URL 之后。

例如，如果先前的表格示例使用 GET 方法 (ACTION = "GET") 且用户键入 Jeff、Smith 和 30，那么下面的 URL 请求将被发送给服务器：

http://scripts/Myfile.asp?firstname=Jeff&lastname=Smith&age=30&userstatus=new

Myfile.asp 包含下面的表格处理脚本：

Hello, <%= Request.QueryString("firstname") %>   <%= Request.QueryString("lastname") %>.
You are  <%= Request.QueryString("age") %>  years old.

<%
If Request.QueryString("userstatus")  = "new user" then
  Response.Write"This is your first visit to this Web site!"
End if
%>

在这种情况下，Web 服务器将返回下面的文本给用户的 Web 浏览器：

Hello, Jeff Smith. You are 30 years old. This is your first visit to this Web site!

QueryString 集合有一个可选参数，可用来访问显示在请求正文中的多个值中的一个。也可以使用 Count 属性计算一个特殊类型的值的出现次数。

例如，表格包含一个多项目的列表框可以提交下面的请求：

http://list.asp?food=apples&food=olives&food=bread

您也可以使用下面的命令去对多个值计数：

Request.QueryString("food").Count

如果想显示多个值的类型，List.asp 应包含下面的脚本；

<%Total = Request.QueryString("food").Count%>
<%For i = 1 to Total%>
  <%= Request.QueryString("food")(i)  %> <BR>
<%Next%>
上述脚本将显示：
apples
olives
bread

Form 集合

当使用 HTTP GET 方法去向 Web 服务器传递长而复杂的表格值时，将可能丢失信息。大多数的 Web 服务器倾向于严格控制 URL 查询字符串的长度，以便用 GET 方法传送的冗长的表格值被截断。如果您需要从表格发送大量信息到 Web 服务器，就必须使用 HTTP POST 方法。此法用于在 HTTP 请求正文中发送表格数据，而且发送的字符的个数可以无限多。也可以使用 ASP Request 对象的 Form 集合检索用 POST 方法发送的值。

Form 集合与 QueryString 集合存储数值的方式相同。例如，如果用户用一长串名称填充表格，您就可以用下面的脚本检索这些名称：

<% For i = 1 to Request.Form.Count %>
<% =Request.Form("names")(i) %>
<% Next %>

验证表格输入

一个好的表格处理脚本在处理数据前，应先验证输入表格的信息是否有效。验证脚本可以检验用户输入到表格的信息类型是否正确。例如，如果您的 Web 站点包含一个表格，该表格允许用户计算财务信息，那么在处理结果之前，需要验证用户确实输入了数值信息而不是文本。

一个非常方便的验证表格输入的方法是创建一个向自身传递信息的表格。在这种情况下，.asp 文件包含可获取信息的表格。例如，下面的脚本通过向自身传递信息来验证用户是否在 "age" 表格字段中输入了数值：

<% If Isnumeric(Request.QueryString("Age")) then %>
  <p>Hello, your age is <%=Request.QueryString("age")%>
<%Else %>
  <p>Please enter a numerical age.
<%End If %>

<FORM METHOD= "POST"  ACTION="verify.asp"  >
Name: <INPUT TYPE="text" NAME="Name" >
Age:  <INPUT TYPE="text" NAME="Age" >
<INPUT TYPE="submit" VALUE="Enter">
</FORM>

在这个例子中，脚本也在包含表格的同一 Verify.asp 文件中。表格通过在 ACTION 属性中指定 Verify.asp 向自身传送信息。

您也可以创建客户端脚本来检验用户是否输入了有效的信息。验证用户在 Web 浏览器上的输入除了更迅速地向用户提示表格项错误外，还可以减少 Web 服务器的网络流量。下面的脚本运行在用户的 Web 浏览器上，在将信息提交到 Web 服务器之前，验证用户信息。

<SCRIPT LANGUAGE="VBScript">
<!--
Sub btnEnter_OnClick
  Dim TheForm
  Set TheForm = Document.MyForm
  If IsNumeric(TheForm.Age.Value) Then
    TheForm.submit
  Else
    Msgbox "Please enter a numerical age."
  End if
End Sub
//-->
</SCRIPT>

<FORM  METHOD= "POST" NAME= MyForm  ACTION="myfile.asp"  >
Name: <INPUT TYPE="text" NAME="Name" >
Age:  <INPUT TYPE="text" NAME="Age" >
<INPUT TYPE="button" NAME="btnEnter"  VALUE="Enter">
</FORM>


访问数据库

ActiveX Data Objects (ADO) 是一项容易使用并且可扩展的将数据库访问添加到 Web 页的技术。可以使用 ADO 去编写紧凑简明的脚本以便连接到 Open Database Connectivity (ODBC) 兼容的数据库和 OLE DB 兼容的数据源。如果您是一个对数据库连接有一定了解的脚本编写人员，那么您将发现 ADO 命令语句并不复杂而且容易掌握。同样地，如果您是一个经验丰富的数据库编程人员，您将会正确认识 ADO 的先进的与语言无关性和查询处理功能。

创建 ODBC DSN 文件

在创建数据库脚本之前，必须提供一条使 ADO 定位、标识和与数据库通讯的途径。数据库驱动程序使用 Data Source Name (DSN) 定位和标识特定的 ODBC 兼容数据库，将信息从 Web 应用程序传递给数据库。典型情况下，DSN 包含数据库配置、用户安全性和定位信息，且可以获取 Windows NT 注册表项中或文本文件的表格。

通过 ODBC，您可以选择希望创建的 DSN 的类型：用户、系统或文件。用户和系统 DSN 存储在 Windows NT 注册表中。系统 DSN 允许所有的用户登录到特定的服务器上去访问数据库，而用户 DSN 使用适当的安全身份证明限制数据库到特定用户的连接。文件 DSN 用于从文本文件中获取表格，提供了对多用户的访问，并且通过复制 DSN 文件，可以轻易地从一个服务器转移到另一个服务器。由于以上原因，本主题中的示例将使用文件 DSN。

通过在 Windows 的“开始”菜单打开“控制面板”，您可以创建基于 DSN 的文件。双击“ODBC”图标，然后选择“文件 DSN”属性页，单击“添加”，选择数据库驱动程序，然后单击“下一步”。按照后面的指示配置适用于您的数据库软件的 DSN。

配置 Microsoft Access 数据库的文件 DSN
  1. 在“创建新数据源”对话框中，从列表框选择“Microsoft Access Driver”，然后单击“下一步”。
  2. 键入您的 DSN 文件名，然后单击“下一步”。
  3. 单击“完成”创建数据源。
  4. 在“ODBC Microsoft Access 97 安装程序”对话框中，单击“选择”。选择 Microsoft Access 数据库文件 (*.mdb)，然后单击“确定”。

注意 由于性能和可靠性的原因，我们极力推荐您使用“客户-服务器数据库引擎”配置由这样一种 Web 应用程序驱动的数据，这些 Web 应用程序必须满足 10 个以上的用户的同时访问。尽管 ASP 可以使用任何 ODBC 兼容的数据库，但它是为使用客户-服务器数据库而设计的，而且经过了严格的测试，这些数据库包括 Microsoft ® SQL Server、Oracle 等。

ASP 支持共享文件数据库（如 Microsoft ® Access 或 Microsoft ® FoxPro）作为有效的数据源。尽管在 ASP 文档中的一些示例使用共享文件数据库，但我们建议只将此类数据库引擎用于开发或有限的配置方案。共享文件数据库可能无法很好地适用于可满足高需求、高质量的 Web 应用程序的客户-服务器数据库。

配置 SQL Server 数据库文件 DSN

注意 如果数据库驻留在远程服务器上，请与服务器管理员联系，获取附加的配置信息；下面的过程使用 SQL Server 的 ODBC 默认的设置，它可能不适用于您的硬件配置。

  1. 在“创建新数据源”对话框中，从列表框中选择“SQL Server”，然后单击“下一步”。
  2. 键入 DSN 文件的名称，然后单击“下一步”。
  3. 单击“完成”创建数据源。
  4. 键入运行 SQL 服务程序的服务器的名称、登录 ID 和密码。
  5. 在“创建 SQL Server 的新数据源”对话框中，在“服务器”列表框中键入包含 SQL Server 数据库的服务器的名称，然后单击“下一步”。
  6. 选择验证登录 ID 的方式。
  7. 如果要选择 SQL 服务器验证，请输入一个登录 ID 和密码，然后单击“下一步”。
  8. 在“创建 SQL Server 的新数据源”对话框中，设置默认数据库、存储过程设置的驱动程序和 ANSI 标识，然后单击“下一步”。（要获取详细信息，请单击“帮助”。）
  9. 在对话框（同样名为“创建 SQL Server 的新数据源”）中，选择一种字符转换方法，然后单击“下一步”。 （详细信息，请单击“帮助”。）
  10. 在下一个对话框（同样名为“创建 SQL Server 的新数据源”）中，选择登录设置。

    11. 注意 典型情况下， 您只能使用日志来调试数据库访问问题。

  11. 在“ODBC Microsoft SQL Server 安装程序”对话框中，单击“测试数据源”。如果 DSN 正确创建，“测试结果”对话框将指出测试成功完成。

    12. SQL server 连接和安全信息

    如果您正在开发用于连接远程 SQL Server 数据库的 ASP 数据库应用程序，应考虑以下问题：

    • 连接方案- 您可以选择 TCP/IP 套接字和命名管道的方法访问远程的 SQL Server 数据库。当使用命名管道时，因为在建立连接之前，数据库用户必须被 Windows NT 确认，所以对只有适当的 SQL Server 访问身份而在该计算机上没有 Windows NT 用户帐号的用户可能会被拒绝访问命名管道。作为一种替代方案，使用 TCP/IP 套接字的连接可直接连接到数据库服务器，而不必通过使用命名管道的中间计算机。因为使用 TCP/IP 套接字连接可直接连接到数据库 server，所以通过 SQL Server 的确认，用户就可以获得访问权，而不必通过 Windows NT 的确认。

      • 注意 在连接到远程数据库时使用 TCP/IP 套接字可提高性能。

    • 安全性 - 如果您使用 SQL Server 的 集成或混合安全特性，并且 SQL Server 数据库位于远程服务器上，则不能使用 Windows NT 请求/响应的确认。也就是说，不能将 Windows NT 请求/响应身份证转发到远程计算机上，而只能使用基本身份验证，它根据用户提供用户名和口令信息进行。

    有关这一主题的详细信息，请参阅http://www.microsoft.com/sqlsupport/
    上的 Microsoft SQL Server 技术支持主页。

配置 Oracle 数据库文件 DSN

首先要确保 Oracle 用户软件被正确地安装要创建 DSN 的计算机上。详细信息，请与服务器管理员联系或参阅数据库软件文档。

  1. 在“创建新数据源”对话框中，从列表框中选择“Microsoft ODBC for Oracle”，然后单击“下一步”。
  2. 键入 DSN 文件的名称，然后单击“下一步”。
  3. 单击“完成”创建数据源。
  4. 输入用户名、密码和服务器名，然后单击“确定”。

注意 DSN 文件用 .dsn 扩展名，位于 \Programs\Common Files\ODBC\Data Sources 目录中。

有关创建 DSN 文件的详细信息，请访问 Microsoft ODBC Web 站点：http://microsoft.com/odbc/。

连接数据库

访问数据库信息的第一步是和数据库源建立连接。ADO 提供 Connection 对象，可以使用该对象建立和管理应用程序和 ODBC 数据库之间的连接。Connection 对象具有各种属性和方法，可以使用它们打开和关闭数据库连接，并且发出查询请求来更新信息。

要建立数据库连接，首先应创建 Connection 对象的实例。例如，下面的脚本创建 Connection 对象，接着打开数据库连接：

<%
  'Create a connection object
  Set cn = Server.CreateObject("ADODB.Connection")
  'Open a connection; the string refers to the DSN
  cn.Open  "FILEDSN=MyDatabase.dsn"
%>

注意 无论在等号 (=) 之前还是之后，DSN 字符串都不能包含空格。

在这种情况下，Connection 对象的 Open 方法引用基于 DSN 的文件，其中包含关于数据库的位置和配置信息。也可以不引用 DSN，直接显式引用供应程序、数据源、用户 ID 和密码。

用 Connection 对象执行查询

用 Connection 对象的 Execute 方法，您可以发出结构化查询语言 (SQL) 查询数据库源并检索结果。SQL 是用于与数据库通讯的工业标准语言，它有许多命令可用来检索和更新信息。

下面的脚本使用 Connection 对象的 Execute 方法在 SQL INSERT 命令的表格中发出查询，该命令将数据插入特定的数据库表格。在下面的示例中，脚本将名称 Jose Lugo 插入名为 Customers 的数据库表中。

<%
  'Define  file based DSN
  strDSN = "FILEDSN=MyDatabase.dsn"

  'Instantiate the Connection object and open a database connection
  Set cn = Server.CreateObject("ADODB.Connection")
  cn.Open strDSN

  'Define SQL SELECT statement
  strSQL = "INSERT INTO Customers (FirstName, LastName) VALUES ('Jose','Lugo')"
  'Use the Execute method to issue a SQL query to database
  cn.Execute(strSQL)

%>

注意 基于 DSN 路径字符串的文件在等号(=)前后不应包含空格。

除了 SQL INSERT 命令以外，您也可以使用 SQL UPDATE 和 DELETE 命令更改和删除数据库信息。

用 SQL UPDATE 命令，您可以改变数据库表中各项目值。下面的脚本使用 UPDATE 命令将 Customers 表中每个 LastName 字段包含姓 Smith 记录的 FirstName 字段更改为 Jeff。

<%
  Set cn = Server.CreateObject("ADODB.Connection")
  cn.Open "FILEDSN=MyDatabase.dsn"
  cn.Execute "UPDATE Customers SET FirstName = 'Jeff' WHERE LastName = 'Smith' "
%>

要想从数据库表中删除特定的记录，可使用 SQL DELETE 命令。下面的脚本从 Customers 表中删除了所有姓 Smith 的行：

<%
  Set cn = Server.CreateObject("ADODB.Connection")
  cn.Open "FILEDSN=MyDatabase.dsn"
  cn.Execute "DELETE FROM Customers WHERE LastName = 'Smith'"
%>

注意 在使用 SQL DELETE 命令时，必须谨慎从事。当使用不带 WHERE 子句的 DELETE 命令时，它将删除表中的所有行。一定要包含 SQL WHERE 子句来指定要删除的确切行。

使用 Recordset 对象处理结果

尽管 Connection 对象简化了连接数据库和查询任务，但 Connection 对象仍有许多不足。确切地说，检索和显示数据库信息的 Connection 对象不能用于创建脚本；您必须确切知道要对数据库作出的更改，然后才能使用查询实现更改。

对于检索数据、检查结果、更改数据库，ADO 提供了 Recordset 对象。正如它的名称所暗示的那样，Recordset 对象有许多您可以使用的特性，根据您的查询限制，检索并且显示一组数据库行，即“记录”。 Recordset 对象保持查询返回的记录的位置，允许您一次一项逐步扫描结果。

根据 Recordset 对象的指针类型属性设置，您可以滚动和更新记录。数据库指针可以让您在一组记录中定位到特定的项。指针还用于检索和检查记录，然后在这些记录的基础上执行操作。Recordset 对象有一些属性，可用于精确地控制指针的行为，提高您检查和更新结果的能力。例如，您可以使用 CursorType 和 CursorLocation 属性设置指针的类型，将结果返回给客户端应用程序（结果通常保留在数据库服务器上）并显示其他用户对数据库的最后一次更改。

检索记录

一个成功的数据库应用程序都使用 Connection 对象建立链接并使用 Recordset 对象处理返回的数据。通过“协调”两个对象的特定功能，您可以开发出几乎可以执行任何数据处理任务的数据库应用程序。例如，下面的服务器端脚本使用 Recordset 对象执行 SQL SELECT 命令。SELECT 命令检索一组基于查询限制的信息。查询也包含 SQL WHERE 子句，用来缩小查询的范围。此例中，WHERE 子句将查询限制为所有的 Customers 数据库表中包含的姓 Smith 的记录。

<%
  'Establish a connection with data source
  strDSN  = "FILEDSN=MyDatabase.dsn"
  Set cn = Server.CreateObject("ADODB.Connection")
  cn.Open strDSN

  'Instantiate a Recordset object
  Set rsCustomers = Server.CreateObject("ADODB.Recordset")

  'Open a recordset using the Open method
  ' and use the connection established by the Connection object
  strSQL = "SELECT FirstName, LastName FROM Customers WHERE LastName = 'Smith' "
  rsCustomers.Open  strSQL, cn

  'Cycle through record set and display the results
  ' and increment record position with MoveNext method
   Set objFirstName = rsCustomers("FirstName")
   Set objLastName = rsCustomers("LastName")
   Do Until rsCustomers.EOF
   Response.Write objFirstName & " " & objLastName & "<BR>"
   rsCustomers.MoveNext
   Loop

%>

注意，在前面的例子中，用来建立数据库连接的 Connection 对象和 Recordset 对象使用该连接从数据库中检索结果。当您需要精确地设置和数据库建立链接所采用的方式时，这个方法是非常有用的。例如，如果您需要在连接尝试失败之前指定等待的时间，则需要使用 Connection 对象去设置属性。但是，如果您仅仅想使用 ADO 默认的连接属性建立连接，则应该使用 Recordset 对象的 Open 方法去建立链接：

<%
  strDSN  = "FILEDSN=MyDatabase.dsn"
  strSQL = "SELECT FirstName, LastName FROM Customers WHERE LastName = 'Smith' "
  Set rsCustomers = Server.CreateObject("ADODB.Recordset")

  'Open a connection using the Open method
  'and use the connection established by the Connection object
  rsCustomers.Open  strSQL, strDSN

  'Cycle through the record set, display the results,
  ' and increment record position with MoveNext method
   Set objFirstName = rsCustomers("FirstName")
   Set objLastName = rsCustomers("LastName")
   Do Until rsCustomers.EOF
      Response.Write objFirstName & " " & objLastName & "<BR>"
   rsCustomers.MoveNext
   Loop
%>

当使用 Recordset 对象的 Open 方法建立一个连接时，必须使用 Connection 对象去保证链接的安全。

用 Command 对象改善查询

通过 ADO Command 对象，可以象用 Connection 对象和 Recordset 对象那样执行查询，唯一的不同在于用 Command 对象您可以在数据库源上准备、编译您的查询并且反复使用一组不同的值来发出查询。这种方式的编译查询的优点是您可以最大程度地减少向现有查询重复发出修改的请求所需的时间。另外，您还可以在执行之前通过您的查询的可变部分的选项使 SQL 查询保持局部未定义。

Command 对象的 parameter 集合减少了您的麻烦，使您不必在每次重新发出查询时重新建立查询。例如，如果需要有规律地更新基于库存清单的 Web 系统中的供应和价格信息，可以用下面的方法预先定义查询：

<%
 'Open a connection using Connection object Command object
 'does not have an Open method for establishing a connection
 strDSN = "FILEDSN=MyDatabase.dsn"
 Set cn = Server.CreateObject("ADODB.Connection")
 cn.Open strDSN

 'Instantiate Command object; use ActiveConnection property to attach
 'connection to Command object
 Set cm= Server.CreateObject("ADODB.Command")
 Set cm.ActiveConnection = cn

 'Define SQL query
 cm.CommandText = "INSERT INTO Inventory (Material, Quantity) VALUES (?, ?)"

 'Save a prepared (or pre-compiled) version of the query specified in CommandText
 'property before a Command object's first execution.
 cm.Prepared = True

 'Define query parameter configuration information
 cm.Parameters.Append cm.CreateParameter("material_type",200, ,255 )
 cm.Parameters.Append cm.CreateParameter("quantity",200, ,255 )

 'Define and execute first insert
 cm("material_type") = "light bulbs"
 cm("quantity") = "40"
 cm.Execute

 'Define and execute second insert
 cm("material_type") = "fuses"
 cm("quantity") = "600"
 cm.Execute
%>

请检查上面的例子，您将注意到，脚本用不同的数值重复构建和发出一个 SQL 查询，而没有重新定义和重发送查询到数据库源。用 Command 对象编译查询也可避免 SQL 查询引起的合并字符串和表格变量问题。特别是，通过使用 Command 对象的 Parameter 集合可以避免与定义字符串、日期、时间变量的类型有关的问题。例如，包含“'”的 SQL 查询值可能导致查询失败：

  strSQL = "INSERT INTO Customers (FirstName, LastName) VALUES ('Robert','O'Hara')"

注意，姓 O'Hara 中包含一个“'”，它与在 SQL VALUES 关键字中用来表示数据的“'”冲突。通过将查询数值作为 Command 对象参数绑定，可以避免此类问题。

结合 HTML 表格和数据库访问

包含 HTML 表格的 Web 页可使用户远程查询数据库并且检索特定的信息。用 ADO 您可以创建非常简单的脚本来收集用户表格信息、创建自定义的数据库查询以及将信息返回给用户。使用 ASP Request 对象，您可以检索输入到 HTML 表格的信息并将这些信息合并到 SQL 语句中。例如，下面的脚本模块将 HTML 表格提供的信息插入表格中。此脚本用 Request 对象的 Form 集合收集用户信息。

<%
 'Open a connection using Connection object. The Command object
 'does not have an Open method for establishing a connection
 strDSN = "FILEDSN=MyDatabase.dsn"
 Set cn = Server.CreateObject("ADODB.Connection")
 cn.Open strDSN

 'Instantiate Command object
 'and  use ActiveConnection property to attach
 'connection to Command object
 Set cm= Server.CreateObject("ADODB.Command")
 Set cm.ActiveConnection = cn

 'Define SQL query
 cm.CommandText = "INSERT INTO MySeedsTable (Type) VALUES (?)"

 'Define query parameter configuration information
 cm.Parameters.Append cm.CreateParameter("type",200, ,255 )

 'Define and execute insert
 cm("type") = Request("SeedType")
 cm.Execute

%>

管理数据库连接

设计一个能经得起考验的 Web 数据库应用程序（例如为几千个客户服务的联机购物应用程序）的最大挑战，在于如何合理地管理数据库连接。打开并且保持数据库连接，即使在没有信息传输时，也会严重耗费数据库服务器的资源并且可能会导致连接性问题。设计良好的 Web 数据库应用程序将回收数据库连接并能够补偿由于网络堵塞造成的延迟。

使连接超时

活动的突然增长可能使数据库服务器变得十分笨拙，大量增加建立数据库连接的时间。结果是，过长的连接延时将降低数据库的性能。

用 Connection 对象的 ConnectionTimeout，您可以限制放弃连接尝试并发出错误消息之前应用程序等待的时间。例如，下面的脚本设置 ConnectionTimeout 属性，在取消连接尝试之前等待 20 秒：

Set cn = Server.CreateObject("ADODB.Connection")
cn.ConnectionTimeout = 20
cn.Open "FILEDSN=MyDatabase.dsn"

默认的 ConnectionTimeout 属性是 30 秒。

注意 在将 ConnectionTimeout 属性合并到数据库应用程序之前，一定要确保连接提供程序和数据源支持该属性。

共享连接

经常建立和中断数据库连接的 Web 数据库应用程序可能会降低数据库服务器的性能。ASP 支持用 ODBC 3.5 的共享特性有效管理连接。连接共享维持打开的数据库连接并管理不同的用户共享该连接，以维持其性能和减少空闲的连接数。对每一个连接请求，连接池首先确定池中是否存在空闲的连接。如果存在，连接池返回连接而不是建立到数据库的新连接。

如果希望将 ODBC 驱动程序加入到连接共享中，则必须配置数据库驱动程序并在 Windows NT 注册表中设置驱动程序的 CPTimeout 属性。当 ODBC 断开连接时，连接被存入池中，而不是被断开。CPTimeout 属性决定在连接池中的连接保留的时间长度。如果在池中连接保留的时间比 CPTimeout 设置的时间长，则连接将被关闭并且从池中删除。CPTimeout 的默认值是 60 秒。

您可以通过创建如下设置的注册表键来有选择地设置 CPTimeout 的属性，从而启用特定 ODBC 数据库驱动程序的连接池：

\HKEY_LOCAL_MACHINE\SOFTWARE\ODBC\ODBCINST.INI\driver-name\CPTimeout = timeout
 (REG_SZ, units are in seconds)

例如，下面的键将 SQL Server 驱动程序的连接池的超时设置定为 180 秒（3 分钟）。

\HKEY_LOCAL_MACHINE\SOFTWARE\ODBC\ODBCINST.INI\SQL Server\CPTimeout = 180

注意 默认情况下，通过将 CPTimeout 设置为 60 秒，Web 服务器将激活 SQL Server 的连接池。

使用跨页连接

尽管您可以通过存储 ASP 的 Application 对象的连接重复使用跨页连接，但是，始终使连接保持打开是不必要的，也没有充分利用连接池的优点。如果有许多用户需要连接到同一个 ASP 数据库应用程序，一个好方法就是，将跨页连接字符串置于 ASP 的 Application 对象中，重复使用数据库连接。例如，可以在 Global.asa 文件的 Application_OnStart 事件过程中指定连接字符串，如下面的脚本所示：

Application.lock
Application("ConnectionString") = "FILEDSN=MyDatabase.dsn"
Application.unlock

然后，在每一个访问数据库的 ASP 文件中写入：

<OBJECT RUNAT=Server ID=cn PROGID="ADODB.Connection"> </OBJECT>

要想创建连接对象的实例，请使用以下脚本：

cn.Open Application("ConnectionString")

对于打开的连接，可以在页尾写入以下脚本，关闭连接：

cn.Close
在单个用户需要重复使用跨页连接的情况下，使用 Session 对象连接比使用 Application 对象更好。

关闭连接

要想更好地使用连接池，就应尽快地关闭数据库连接。默认情况下，当脚本执行完以后，连接将被终止。当不再需要连接时将其关闭，就可以减少对数据库服务器的要求并可以使其他用户能够使用该连接。

可以使用 Connection 对象的 Close 方法终止 Connection 对象和数据库之间的连接。下面的脚本打开连接，然后将其关闭：

<% strDSN = "FILEDSN=MyDatabase.dsn"
Set cn = Server.CreateObject("ADODB.Connection")
cn.Open
cn.Close
%>


调试 ASP 脚本

无论您的计划多么精密、经验多么丰富，脚本错误 (bug) 可能在最初就使您的 ASP 服务器端的脚本无法正确运行。也就是说调试，即查找和纠正脚本错误，对开发一个成功的和强健的 ASP 程序是非常重要的。

Microsoft 脚本调试工具

Microsoft® Script Debugger 是一个功能强大的调试工具，它能帮助您迅速查找错误并对服务器端的脚本进行交互测试。Script Debugger 与 Windows Internet Explorer 3.0 版本或更新的版本一起工作。通过它，您可以：

  • 逐行运行服务器端脚本。
  • 在服务器端脚本执行时，打开命令窗口监视变量、属性或数组元素的值。
  • 在特定行设置暂停标记，挂起服务器端脚本（使用调试工具或脚本命令）。
  • 在运行服务器端脚本时跟踪过程。

注意 您可以使用调试工具查看脚本并找到错误所在，但是不能直接编辑脚本。要想改正错误，必须用编辑器编辑脚本然后保存，再运行脚本。

（该功能不能用于 Windows 95 或更高的版本。）

启用调试

在开始调试服务器端脚本之前，您必须首先配置 Web 服务器，使其支持 ASP 调试。

在启用 Web 服务器调试之后，就可以使用下面的任一方法调试脚本：

  • 手工打开 Microsoft 脚本调试器，调试 ASP 服务器端脚本。
  • 使用 Internet Explorer 请求 .asp 文件。如果该文件包含错误或人为添加的停止执行语句，那么 Microsoft 脚本调试程序将自动启动，显示该脚本，并且指出错误来源。

脚本错误

调试服务器端脚本时，您可能会碰到各种类型的错误。其中的某些错误使脚本无法正确执行、程序停止执行或返回错误结果。

语法错误

语法错误是经常碰到的错误，它是由不正确的脚本语法导致的。例如，命令拼写错误或传递给函数的参数不正确都将产生错误。语法错误可能导致您的脚本不能运行。

运行时错误

运行时错误是脚本在执行过程中脚本指令试图执行不可能的动作而导致的。例如，下面的脚本中包含一个被零除（一种非法的数学运算）的函数，将产生运行时错误：

<script language = "VBScript" runat = server>
  Result = Findanswer(15)
  document.write ("The answer is " &Result)

  Function Findanswer(x)
  'This statement generates a run-time error.
   Findanswer = x/0
  End Function
</script>

必须纠正导致运行时错误的错误，这样才能使脚本在运行时不被中断。

逻辑错误

逻辑错误通常可能是潜在和难以检测的。如果有因键入错误或程序逻辑流程错误引起的逻辑错误，脚本可能会成功运行，但产生的结果却是错的。例如，一服务器端脚本计划对一个值列表排序，如果本应使用 “<” 符号比较数值，但却使用了“ >” 符号，那么将返回不正确的排序结果。

错误调试技术

可以使用多种不同的调试技术来查找错误的根源并测试应用程序。

实时 (Just-In-Time, JIT) 调试

当一个运行时错误中断了 ASP 脚本的执行时，Microsoft 脚本调试程序自动启动，显示 .asp 文件，将语句指针指向导致错误的行，并产生错误消息。这种调试方式称为实时 (JIT) 调试，计算机将暂停程序的执行。必须用编辑程序纠正这些错误，保存所做的修正，然后再运行脚本。

断点调试

当一个错误发生并且很难找到错误的根源时，可使用预设断点的调试方法。断点将脚本暂停在特定一行。可以在脚本中有疑问处设置一个或多个不同的断点，然后使用调试器去改正脚本中设置的变量或属性的值。当您纠正这些错误之后，可以清除断点以便您的脚本能不间断地运行。

请用 Microsoft 脚本调试程序打开脚本，设置断点。然后用 Web 浏览器请求此脚本。当执行到脚本中含有断点的行时，计算机启动脚本调试程序，并且语句指针会指在设置了断点的行上。

VBScript Stop 语句调试器

通过在服务器端脚本中有问题的部分前面插入 Stop 语句，您也可以将断点添加到用 VBScript 编写的服务器端脚本中。例如，下面的 ASP 脚本包含一个 Stop 语句，用来在显示结果之前暂停执行：

<%
  dayvalue = 3
  TheDay  =  WeekDayName(dayvalue)
  Stop			'set breakpoint here.
  Response.Write("Today is " + TheDay)
%>

当您在请求 Web 浏览器使用的先前的脚本时，调试程序启动并自动显示 .asp 文件，而且语句指针会指示 stop 语句的位置。一定要记住从交付使用的 .asp 文件中删除 Stop 语句。

用 JScript Debugger 语句调试

要将断点加到用 Microsoft® JScript 编写的服务器端脚本中，可在有疑问的行前插入 debugger 语句。例如，下面的脚本包含了 debugger 语句，每次脚本循环到一个新值时，就会中断执行并自动启动 Microsoft 脚本调试程序。

<%@ Language="JScript"  %>
<%
  for (var count = 1; count <= 10; count++)  {
    var eventest = count%2;
    debugger			      //Sets breakpoint
    if (eventest == 0) {
      response.write("Even value is " + count + "<br>")
    }
  }
%>

请记住从交付使用的 .asp 文件中删除 debugger 语句。

注意 不要混淆 debugger 语句和 JScript break 语句。在程序执行期间，break 语句仅退出当前循环，并不激活 Microsoft 脚本调试器，也不暂停程序的执行。

脚本调试技巧

除脚本调试程序外，一套好的调试技巧也能减少花费在分析脚本错误根源上的大量时间。尽管大部分错误是由显而易见的根源导致的，但命令拼写错误或丢失变量、某种类型的逻辑和执行错误也可能因不太明显的根源所致。


ASP 应用程序

本部分包含适用于 ASP 应用程序的主题。

其中包括：

  • 关于 ASP 应用程序：解释什么是 ASP 应用程序。
  • 管理应用程序：解释如何启动和停止应用程序并介绍部分应用程序管理服务。
  • 管理会话：解释如何保存用户信息。
  • 维护 ASP 应用程序的安全：解释如何通过验证用户标识和控制对应用程序中的文件的访问来维护应用程序的安全。
  • 创建事务性脚本：解释如何在事务环境中运行脚本。
  • 使用多语言站点：解释如何为应用程序设置代码页（字符编码）和现场格式。
  • 编写跨平台应用程序：解释如何在 Macintosh 机上编写能够在 Windows NT 上配置的应用程序。

本部分不包括以下信息：

  • 有关 ASP 内建对象的参考页；
  • 有关与 ASP 一同提供的控件；
  • 创建自己的 ASP 组件；
  • VBScript 的参考信息；
  • JScript 的参考信息；
  • 与 SDK 一同提供的脚本范例。


关于 ASP 应用程序

基于 ASP 的应用程序是 ASP 页和 ActiveX 组件的集合。当用户定义应用程序时，将使用 Internet 服务管理器指定用户的 Web 站点中应用程序启动点的目录。在用户的 Web 站点中每个位于启动点目录下的文件和文件夹都被认为是应用程序的一部分，直到发现另外的启动点目录为止。这样，用户就可以使用目录作为边界定义应用程序的作用域。每个 Web 站点可以有多个应用程序，而每个应用程序的配置都可以不同。


管理应用程序

Windows NT Option Pack 提供了在 Web 服务器上的 ASP 应用程序管理服务。例如，Internet 服务管理器为应用程序开发人员提供了一个使用简便的管理工具来设置应用程序的属性。另外，Active Server Pages 提供了允许用户的应用程序存储全局数据的脚本功能。本主题简要介绍部分应用程序管理功能，并提供到详细信息的链接。

启动和结束应用程序

当 Web 服务器第一次收到应用程序中的 ASP 页的请求时，就启动该应用程序。当 Web 服务器关闭或用户使用 Internet 服务管理器上的“卸载”按钮停止应用程序时，应用程序便结束。用户只能对运行在与 Web 服务器进程不同的内存空间（被隔离的）中的应用程序使用“卸载”按钮。

隔离一项应用程序

ASP 应用程序通常与 Web 服务器运行在同一内存空间或同一进程中。虽然这样改善了 ASP 应用程序的性能，但如果应用程序失败， Web 服务器进程则处于危险境地。您可以通过使应用程序运行在不同于 Web 服务器的内存空间上而隔离此应用程序。如果 ASP 应用程序失败，其他应用程序和 Web 服务器本身受到保护。

使用应用程序状态

在编写应用程序时，应让应用程序的所有用户都能获得与应用程序有关的信息。例如，创建一些变量，使系统管理员能够通过设置不同的欢迎画面或改变所有的 ASP 页的标题字体来自定义其站点的应用程序。这些更改将被所有访问该站点的用户所看到。

有多种方式可使应用程序的所有用户从应用程序的所有页上获得数据。最常用的方法为将变量或对象实例存储在 ASP Application 对象中，为其赋予应用程序作用域。应用程序作用域对全局数据十分有用，例如全局数据计数器或全局应用程序配置信息，还例如存储在注册表或元数据库中的信息。要了解如何赋予变量应用的范围，请参阅使用变量。要了解如何赋予对象应用的范围，请参阅设置对象的作用域。

也可以编写应用程序启动或关闭时都要运行的脚本。


管理会话

成功开发 Web 应用程序的难题之一是在一次用户访问，即会话期间，当用户在一个应用程序的页与页之间跳转的同时，维护用户信息。HTTP 是一种无状态协议，也就是说，Web 服务器将某页的每次访问都当作相互无关的访问来处理；服务器不保留前一次访问的任何信息，即使访问就发生在当前访问的几秒钟之前。正因为这种不记忆以前访问的特性使得编写联机目录之类的应用程序很困难，此类应用程序可能需要跟踪用户在目录的不同页间跳转的同时曾选择过的目录项。

ASP 提供了一个管理会话信息问题的独特方案。使用 ASP Session 对象和由您的服务器生成的特殊用户 ID，您可以创建一个智能应用程序，该应用程序可以识别每个来访的用户并收集应用程序跟踪用户的首选项或选择内容所要用到的信息。

ASP 通过 HTTP cookie 设置用户 ID。HTTP cookie 是存储在用户浏览器上的小文件。因此，如果您正在为不支持 cookie 的浏览器创建应用程序，或者您的客户将浏览器设置为不接受 cookie，请不要使用 ASP 的会话管理功能。

您也可以编写在应用程序启动或结束时运行的脚本。

启动和结束会话

会话可以通过三种方式启动：

  • 一个新用户请求访问一个 URL，该 URL 标识了某个应用程序中的 .asp 文件，并且该应用程序的 Global.asa 文件包含 Session_OnStart 过程。
  • 用户在 Session 对象中存储了一个值。
  • 用户请求了一个应用程序的 .asp 文件，并且该应用程序的 Global.asa 文件使用 <OBJECT> 标签创建带有会话作用域的对象的实例。

如果用户在指定时间内没有请求或刷新应用程序中的任何页，会话将自动结束。这段时间的默认值是 20 分钟。可以通过在 Internet 服务管理器中设置“应用程序选项”属性页中的“会话超时”属性改变应用程序的默认超时限制设置。应依据您的 Web 应用程序的要求和服务器的内存空间来设置此值。例如，如果您希望浏览您的 Web 应用程序的用户在每一页仅停留几分钟，就应该缩短会话的默认超时值。过长的会话超时值将导致打开的会话过多而耗尽您的服务器的内存资源。

对于一个特定的会话，如果您想设置一个小于默认超时值的超时值，可以设置 Session 对象的 Timeout 属性。例如，下面这段脚本将超时值设置为 5 分钟。

<%  Session.Timeout = 5  %>

您也可以设置一个大于默认设置的超时值，Session.Timeout 属性决定超时值。

您也可以通过 Session 对象的 Abandon 方法显式结束一个会话。例如，在表格中提供一个“退出”按钮，将按钮的 ACTION 参数设置为包含下列命令的 .asp 文件的 URL 。

<% Session.Abandon %>

关于 SessionID 和 Cookie

当用户第一次请求给定的应用程序中的 .asp 文件时，ASP 生成一个 SessionID。SessionID 是由一个复杂算法生成的号码，它唯一标识每个用户会话。在新会话开始时，服务器将 Session ID 作为一个 cookie 存储在用户的 Web 浏览器中。

SessionID 与钥匙很相似，当会话期间用户与应用程序交互时，ASP 可以将用户信息存储在服务器的一个“保险箱”中。正象用钥匙能存取保险箱中物品一样，通过在 HTTP 请求标题中发送的用户 SessionID cookie，就能够对该“保险箱”中的内容进行访问。每当 ASP 收到一个页请求时，就检查 HTTP 请求标题，以获得 SessionID cookie。

在将 SessionID cookie 存储于用户的浏览器之后，即使用户请求了另一个 .asp 文件，或请求了运行在另一个应用程序中的 .asp 文件，ASP 仍会重用该 cookie 跟踪会话。与此相似，如果用户故意放弃会话或让会话超时，然后再请求另一个 .asp 文件，那么 ASP 将以同一个 cookie 开始新的会话。只有当服务器管理员重新启动服务器或用户重新启动 Web 浏览器时，此时存储在内存中的 SessionID 设置将被清除,用户将会获得新的 SessionID cookie。

通过重用 SessionID cookie，ASP 将发送给用户浏览器的 cookie 数量降为最低。另外，如果您决定您的 ASP 应用程序不需要会话管理，就可以不让 ASP 跟踪会话和向用户发送 SessionID 。

ASP 在以下情况下不发送会话的 cookie：

  • 应用程序的会话状态被禁用。
  • ASP 页被定义为无会话，即该页包含 <%@ EnableSessionState=False %> 标记。

请注意，SessionID cookie 并不提供跟踪用户对某个 Web 站点的多次访问的永久方法。存储在服务器内存中的 SessionID 信息很容易丢失。如果想跟踪在很长时间内访问您的 Web 应用程序的用户，必须通过在用户的 Web 浏览器中存储一个专门的 cookie，并将 cookie 信息保存到数据库中来创建一个用户标识。

在 Session 对象中存储数据

Session 对象提供了一个可在其中存储信息的动态关联数组。您可以在 Session 对象中存储数值变量和对象变量。

通过对 Session 对象中的命名项赋值，可将变量存储在 Session 对象中。例如，以下命令将两个新变量存储在 Session 对象中：

<%
Session("FirstName") = "Jeff"
Session("LastName") = "Smith"
%>

通过访问该命名项可从 Session 对象中获取信息。例如，显示 Session("FirstName") 的当前值：

Welcome <%= Session("FirstName") %>

可以在 Session 对象中存储用户的首选项，然后通过访问首选项来决定将哪一页发送给用户。例如，可以允许用户在您的应用程序的第一页中指定纯文本版本的内容并将这一选择应用到用户此后对该应用程序的所有页的访问上。

<% If Session("ScreenResolution") = "Low" Then %>
This is the text version of the page.
<% Else %>
This is the multimedia version of the page.
<% End If %>

您也可以在 Session 对象中存储一个对象实例，但这样做会影响服务器的性能。

管理 Web Farm 的会话

ASP 会话信息存储在 Web 服务器中。浏览器必须向 Web 服务器请求页才能获得用来访问会话信息的脚本。在 Web Farm（其中许多 Web 服务器共同承担响应用户申请的责任）中，用户的请求并不总是被路由到同一个服务器，而是由一个被称为“负载平衡”进程的特殊软件对此 URL 站点的申请分配任意一个空闲的服务器。负载平衡进程使在 Web Farm 中保存会话信息变得更加困难。

为了在一个负载被平衡的站点上使用 ASP 会话管理，必须保证用户会话的所有请求都被定向到同一个 Web 服务器。一种做法是编写一个 Session_OnStart 过程，此过程使用 Response 对象将浏览器重定向到运行该用户会话的 Web 服务器。如果在您的应用程序页中的所有链接都是相对的，那么以后对某一页的所有请求都将被路由到同一个服务器。

例如，某用户要通过请求某一站点的通用 URL：http://www.microsoft.com 来访问一个应用程序。负载平衡进程将申请路由到服务器 server3.microsoft.com。ASP 在此服务器上生成了一个新的用户会话。在 Session_OnStart 过程中，浏览器被重定向给指定的服务器：

<% Response.Redirect("http://server3.microsoft.com/webapps/firstpage.asp") %>

浏览器将请求指定的页，并且以后的所有请求都将被路由到同一个服务器。

使用 Cookie

cookie 是 Web 服务器嵌在用户的 Web 浏览器中，用来代表用户的令牌。当下次同一浏览器请求一页时，它将发送从 Web 服务器收到的 cookie。 cookie 允许有一组信息与用户关联。 ASP 脚本使用 Response 和 Request 对象的 Cookies 集合，可以获取和设置 cookie 的值。

设置 cookie

要设置 cookie 的值，可使用 Response.Cookies。如果 cookie 不存在，Response.Cookies 将创建新的 cookie。例如，要向浏览器发送一个有关联值 ("Mars") 的 cookie 名 ("planet")，可使用下列命令，这些命令必须出现在您的 Web 页的 <HTML> 标记前：

<% Response.Cookies("planet")="Mars" %>

如果您只希望 cookie 在当前的用户会话中被使用，则只需向浏览器发送 cookie。但是，如果要在用户已经终止或重新启动浏览器之后确认用户，就必须强制浏览器将 cookie 存储在计算机的硬盘上。要保存 cookie，可使用 Response.Cookies 的 Expires 属性并将日期设置为此后的某一天：

<%
Response.Cookies("planet") = "Mars"
Response.Cookies("planet").Expires = "January 1, 1999"
%>

cookie 可有多个值；这样的 cookie 被称为一个带索引的 cookie。每个 cookie 值都被赋予一个关键字；您可以设置一个特定的 cookie 关键字的值。例如：

<% Response.Cookies("planet")("Mars")="SpaceMissions" %>

如果某个现有的 cookie 具有关键字值但 Response.Cookies 未指明一个关键字的名称，则该关键字值将被删除。类似的，如果某个现有的 cookie 没有关键字值但 Response.Cookies 指明了关键字的名称和值，则现有的 cookie 值将被删除，并生成新的 key-value 对。

获取 cookie

要获取 cookie 的值，可使用 Request.Cookies 集合。例如，如果用户的 HTTP 请求设置了 planet=Mars，则下列语句将获取值 Mars：

<%= Request.Cookies("planet") %>

相似的，要从带索引的 cookie 中获取关键字值，可使用关键字名。例如，如果用户发出下列的 HTTP 请求：

planet=Mars&Mars=SpaceMissions

下列脚本将返回值 SpaceMissions：

<%= Request.Cookies("planet")("Mars") %>

设置 cookie 路径

由 ASP 存储在用户的 Web 浏览器中的每个 cookie 都包含路径信息。当浏览器请求的文件的位置与在 cookie 中指定的路径相同时，浏览器自动将 cookie 转发给服务器。默认情况下，cookie 路径与包含最初生成 cookie 的 .asp 文件的应用程序名对应。例如，如果在名为 UserApplication 的应用程序中的 .asp 文件生成了一个 cookie，那么每当用户的 Web 浏览器在此应用程序中获取文件时，除其他在路径 /UserApplication 下的 cookie 外，浏览器还要将该 cookie 转发给服务器。

要给 cookie 声明一个不同于默认的应用程序路径的路径，可以使用 ASP 的 Response.Cookies 集合的 Path 属性。例如，下列脚本将路径 SalesApp/Customer/Profiles/ 赋予名为 Purchases 的 cookie：

<%
Response.Cookies("Purchases") = "12"
Response.Cookies("Purchases").Expires = "January 1, 2001"
Response.Cookies("Purchases").Path = "/SalesApp/Customer/Profiles/"
%>

每当包含 Purchases cookie 的 Web 浏览器请求位于路径 /SalesApp/Customer/Profiles/ 或其子目录的文件时，浏览器将 cookie 转发给服务器。

许多 Web 浏览器，包括 Microsoft Internet Explorer 4.0 和 Netscape 浏览器，保留 cookie 路径的大小写。也就是说，如果一个被请求的文件的大小写与保留的 cookie 路径不同，那么浏览器是不会向服务器转发 cookie 的。例如，对于 ASP，虚拟目录 /TRAVEL 和 /travel 是相同的 ASP 应用程序，而对于保留 URL 的大小写的浏览器而言，/TRAVEL 和 /travel 则是两个不同的应用程序。应确保 .asp 文件的所有 URL 具有相同的大小写，以保证用户的浏览器能够转发存储的 cookie。

如果需要，可使用下列语句设置 cookie 路径，使得无论应用程序或路径是什么，只要用户的 Web 浏览器向您的服务器请求文件，就会转发 cookie ：

Response.Cookies("Purchases").Path = "/"

但是，请注意，在不区分应用程序的情况下向服务器发送 cookie，如果 cookie 包含不应被指定应用程序以外的程序访问的敏感信息，就可能产生安全性问题。

不使用 cookie 而保留状态

并不是所有的浏览器都支持 cookie。即便使用支持 cookie 的浏览器，有些用户也可能喜欢关闭 cookie 支持。如果您的应用程序需要响应不支持 cookie 的浏览器，就必须使用 ASP 会话管理。

如果您不使用 ASP 会话管理，就必须编写您自己的机制以便在您的应用程序页之间传递信息。有两种常规的方法可完成该任务：

  • 向 URL 的查询字符串添加参数。例如：
    • http://MyServer/MyApp/start.asp?name=Jeff

    但是，某些浏览器，在表格被以 GET 方法提交的情况下会丢弃查询字符串中传递的显式参数。

  • 向表格中添加隐含值。例如，以下的 HTML 表格包含一个隐含的控件。此控件在真正的表格中不出现，而且对用户的 Web 浏览器是不可见的。通过 HTTP POST 方法，表格除了传递用户提供的信息外，还传递用户标识。
    • <FORM METHOD="POST" ACTION="/scripts/inform.asp">
<INPUT TYPE="text" NAME="city" VALUE="">
<INPUT TYPE="text" NAME="country" VALUE ="">
<INPUT TYPE="hidden" NAME="userid" VALUE= <%=UserIDNum(i) %>
<INPUT TYPE="submit"  VALUE="Enter">

    本方法要求传输用户信息的所有链接目标被编码为 HTML 表格。

如果您当前没有使用 ASP 会话管理，请关闭您的应用程序会话支持。当会话启用时，ASP 向每个请求 ASP 页的浏览器发送 SessionID cookie。要关闭会话支持，可清除 Internet 服务管理器中的“应用程序选项”属性页中的“启用会话状态”复选框。

无会话的 ASP 页

ASP 也提供创建无会话页的功能，您可以使用该功能将会话的创建时间推迟到用户访问一个需要会话跟踪的 ASP 页时。

无会话页不执行以下功能：

  • 执行 Session_OnStart 过程。
  • 发送会话 ID cookie。
  • 创建 Session 对象。
  • 访问用 <OBJECT> 标记创建的内建会话对象或会话作用域对象。
  • 与其他会话请求顺序执行。

要将 .asp 配置为无会话，可使用下列语句：

<%@ EnableSessionState=False %>

您应将此脚本置于 .asp 文件的第一行，位于其他脚本之前。默认情况下，若省略此标记，则启用会话跟踪。

无会话 ASP 页通过消除潜在的耗时会话操作，改善服务器的响应性能。例如，考虑以下情况，ASP 页包含某个帧集中的两个 HTML 帧，帧 1 和 帧 2。帧 1 包含一个执行复杂脚本的 .asp 文件，而帧 2 包含一个简单的 .html 文件。因为 ASP 顺序执行（即串行执行）会话请求，所以在帧 1 的脚本被执行之前，您将不会看到帧 2 的内容。但是，如果您将帧 1 设置为无会话，则 ASP 请求将不再被串行处理，浏览器不必等待执行完帧 1 的内容就可以处理帧 2 的内容。

但是，不同帧的多个请求的处理方式最终还要取决于用户 Web 浏览器的配置。某些 Web 浏览器可能不理会您的 .asp 文件的无会话配置，照样串行处理请求。


维护 ASP 应用程序的安全

千万不要轻视正确配置安全设置的重要性。如果不正确配置安全设置，不但会使您的 ASP 应用程序遭受不必要的篡改，而且会妨碍正当用户访问您的 .asp 文件。

Web 服务器提供了各种方法来保护您的 ASP 应用程序免受未授权的访问和篡改。在您读完本主题下的安全信息之后，请花一定的时间仔细检查一下您的 Windows NT 和 Web 服务器安全性文档。

NTFS 权限

您可以通过为单独的文件和目录应用 NTFS 访问权限来保护 ASP 应用程序文件。NTFS 权限是 Web 服务器安全性的基础，它定义了一个或一组用户访问文件和目录的不同级别。当拥有 Windows NT 有效帐号的用户试图访问一个有权限限制的文件时，计算机将检查文件的访问控制表 (ACL)。该表定义了不同用户和用户组所被赋予的权限。如果用户的帐号具有打开文件的权限，计算机则允许该用户访问文件。例如，Web 服务器上的 Web 应用程序的所有者需要有“更改”权限来查看、更改和删除应用程序的 .asp 文件。但是，访问该应用程序的公共用户应仅被授予“只读”权限，以便将其限制为只能查看而不能更改应用程序的 Web 页。

维护 Global.asa 的安全

为了充分保护 ASP 应用程序，一定要在应用程序的 Global.asa 文件上为适当的用户或用户组设置 NTFS 文件权限。如果 Global.asa 包含向浏览器返回信息的命令而您没有保护 Global.asa 文件，则信息将被返回给浏览器，即便应用程序的其他文件被保护。

注意 一定要对应用程序的文件应用统一的 NTFS 权限。例如，如果您不小心过度限制了一应用程序需要包含的文件的 NTFS 权限，则用户可能无法查看或运行该应用程序。为了防止此类问题，在为您的应用程序分配 NTFS 权限之前应仔细计划。

Web 服务器权限

您可以通过配置您的 Web 服务器的权限来限制所有用户查看、运行和操作您的 ASP 页的方式。不同于 NTFS 权限提供的控制特定用户对应用程序文件和目录的访问方式， Web 服务器权限应用于所有用户，并且不区分用户帐号的类型。

对于要运行您的 ASP 应用程序的用户，在设置 Web 服务器权限时，必须遵循下列原则：

  • 对包含 .asp 文件的虚拟目录允许“读”或“脚本”权限。
  • 对 .asp 文件和其他包含脚本的文件（如 .htm 文件等）所在的虚目录允许“读”和“脚本”权限。
  • 对包含 .asp 文件和其他需要“执行”权限才能运行的文件（如 .exe 和 .dll 文件等）的虚目录允许“读”和“执行”权限。

脚本映射文件

应用程序的脚本映射保证了 Web 服务器不会意外地下载 .asp 文件的源代码。例如，即使您为包含了某个 .asp 文件的目录设置了“读”权限，只要该 .asp 文件隶属于某个脚本映射应用程序，那么您的 Web 服务器就不会将该文件的源代码返回给用户。

Cookie 安全性

ASP 使用 SessionID cookie 跟踪应用程序访问或会话期间特定的 Web 浏览器的信息。这就是说，带有相应的 cookie 的 HTTP 请求被认为是来自同一 Web 浏览器。Web 服务器可以使用 SessionID cookies 配置带有用户特定会话信息的 ASP 应用程序。例如，如果您的应用程序是一个允许用户选择和购买 CD 唱盘的联机音乐商店，就可以用 SessionID 跟踪用户漫游整个应用程序时的选择。

SessionID 能否被黑客猜中？

为了防止计算机黑客猜中 SessionID cookie 并获得对合法用户的会话变量的访问，Web 服务器为每个 SessionID 指派一个随机生成号码。每当用户的 Web 浏览器返回一个 SessionID cookie 时，服务器取出 SessionID 和被赋予的数字，接着检查是否与存储在服务器上的生成号码一致。若两个号码一致，将允许用户访问会话变量。这一技术的有效性在于被赋予的数字的长度（64 位），此长度使计算机黑客猜中 SessionID 从而窃取用户的活动会话的可能性几乎为 0。

加密重要的 SessionID Cookie

截获了用户 sessionID cookie 的计算机黑客可以使用此 cookie 假冒该用户。如果 ASP 应用程序包含私人信息，信用卡或银行帐户号码，拥有窃取的 cookie 的计算机黑客就可以在应用程序中开始一个活动会话并获取这些信息。您可以通过对您的 Web 服务器和用户的浏览器间的通讯链路加密来防止 SessionID cookie 被截获。

使用身份验证机制保护被限制的 ASP 内容

您可以要求每个试图访问被限制的 ASP 内容的用户必须要有有效的 Windows NT 帐号的用户名和密码。每当用户试图访问被限制的内容时，Web 服务器将进行身份验证，即确认用户身份，以检查用户是否拥有有效的 Windows NT 帐号。

Web 服务器支持以下几种身份验证方式：

  • 基本身份验证 提示用户输入用户名和密码。
  • Windows NT 请求/响应式身份验证 从用户的 Web 浏览器通过加密方式获取用户身份信息。

然而，Web 服务器仅当禁止匿名访问或 Windows NT 文件系统的权限限制匿名访问时才验证用户身份。

保护元数据库

访问元数据库的 ASP 脚本需要 Web 服务器所运行的计算机的管理员权限。在从远程计算机上运行这些脚本时，须经已通过身份验证的连接，如使用 Windows NT 请求/响应验证方式进行连接。应该为管理级 .asp 文件创建一个服务器或目录并将其目录安全验证方式设置为 Windows NT 请求/响应式身份验证。目前，仅 Microsoft Internet Explorer version 2.0 或更高版本支持 Windows NT 请求/响应式身份验证。

使用 SSL 维护应用程序的安全

Secure Sockets Layer (SSL) 3.0 协议作为 Web 服务器安全特性，提供了一种安全的虚拟透明方式来建立与用户的加密通讯连接。SSL 保证了 Web 内容的验证，并能可靠地确认访问被限制的 Web 站点的用户的身份。

通过 SSL，您可以要求试图访问被限制的 ASP 应用程序的用户与您的服务器建立一个加密连接；以防用户与应用程序间交换的重要信息被截取。

维护包含文件的安全

如果您从位于没有保护的虚拟根目录中的 .asp 文件中包含了位于启用了 SSL 的目录中的文件，则 SSL 将不被应用于被包含文件。因此，为了保证应用 SSL，应确保包含及被包含的文件都位于启用了 SSL 的目录中。

客户资格认证

控制对您的 ASP 应用程序访问的一种十分安全的方法是要求用户使用客户资格登录。客户资格是包含用户身份信息的数字身份证，它的作用与传统的诸如护照或驾驶执照等身份证明相同。用户通常从委托的第三方组织获得客户资格，第三方组织在发放资格证之前确认用户的身份信息。（通常，这类组织要求姓名、地址、电话号码及所在组织名称；此类信息的详细程度随给予的身份等级而异。）

每当用户试图登录到需要资格验证的应用程序时，用户的 Web 浏览器会自动向服务器发送用户资格。如果 Web 服务器的 Secure Sockets Layer (SSL) 资格映射特性配置正确，那么服务器就可以在许可用户对 ASP 应用程序访问之前对其身份进行确认。

用于处理资格证明的 ASP 脚本

作为 ASP 应用程序开发人员，您可以编写脚本来检查资格是否存在并读取资格字段。例如，您可以从资格证明中访问用户名字段和公司名字段。Active Server Pages 在 Request 对象的 ClientCertificate 集合中保存资格信息。

必须将 Web 服务器配置为接受或需要客户资格，然后才能通过 ASP 处理客户资格；否则，ClientCertificate 集合将为空。


创建事务性脚本

商业应用程序常常需要具有在事务内部运行脚本和组件的能力。事务是一种服务器操作，即使该操作包括很多步骤（例如，定货、查看存货、付帐等），也只能整体返回操作是成功还是失败。用户可以创建在事务内部运行的 ASP 脚本，如果脚本的任何一部分失败，整个事务都将会终止。

ASP 事务处理是以 Microsoft® Transaction Server (MTS) 为基础的。Microsoft® Transaction Server (MTS) 是一个事务处理系统，用于开发、配置和管理高性能、可分级的、有鲁棒性的企业 Internet 和 Intranet 服务器应用程序。Transaction Server 为开发分布式的，基于组件的应用程序提供了一个应用程序设计模型。它也为配置和管理这些应用程序提供了一个运行环境。

创建事务性脚本的功能内置在 Internet Information Server 和 Personal Web Server 中。如果您安装了 Microsoft Transaction Server，就可以将组件打包，以使组件在事务内部运行。

关于事务

事务是整体成功或失败的操作。事务处理用于对数据库进行可靠地更新。在对数据库进行许多相关更改或同时更新多个数据库时，要保证所有更改都被正确执行。如果这些更改中的任何一个失败，都需要恢复数据库表的原始状态。

如果没有 MTS，您就需要编写脚本和组件，手工跟踪请求的更改情况，以便在某些更改失败时恢复数据。使用 MTS，您只需简单的将您的脚本和组件声明为“需要事务”并让 MTS 处理事务的一致性。事务处理只适用于数据库访问；MTS 不能对文件系统或其他的非事务性资源的更改进行恢复操作。应用程序所访问的数据库必须为 MTS 所支持。目前，MTS 支持 SQL Server 及任何支持 XA 协议（由 X/Open 协会制定）的服务器。MTS 将继续扩展对其他数据库的支持。

事务不能跨越多个 ASP 页。如果一个事务需要来自多个组件的对象，则须将使用这些对象的操作组合在一个 ASP 页中。例如，假定有一个组件用于更新工资单数据库，还有一个组件用于更新人力资源数据库中的员工记录。为了记录一个员工的新的工资信息，您需要编写这样一个脚本，该脚本在一个事务环境中调用这两个组件，一个用于更新工资单数据库，另一个用于更新人力资源数据库中的员工等级。

声明事务性脚本

在将一个页声明为事务性时，此页中的任何脚本命令和对象都运行在同一个事务环境中。Transaction Server 处理生成事务的细节并决定事务成功（提交）或失败（终止）。要将某个页声明为事务性，可在页首添加 @TRANSACTION 指令：

<%@ TRANSACTION = value %>

value 参数可以是下列之一：

值 | 意义
Requires_New | 启动一个新的事务。
Required | 启动一个新的事务。
Supported | 不启动事务。
Not_Supported | 不启动事务。

@TRANSACTION 指令必须在一页中的第一行，否则将产生错误。必须将该指令添加到需要在事务下运行的每一页中。当脚本处理结束时，当前事务即告结束。

大多数应用程序只有一些特定的操作需要事务环境。例如，一个航空公司的站点可能只需要事务性脚本处理购票和安排座位，而其他所有脚本则无须事务环境即可安全运行。因为事务只须用于需要事务处理的页即可，不要将应用程序的 Global.asa 文件声明为事务性。

如果事务被终止，Transaction Server 将恢复对支持事务的资源的任何更改。目前，仅数据库服务器完全支持事务，因为数据库中的数据对于企业应用是最为关键的。Transaction Server 不对硬盘上的文件、会话和应用程序的变量、集合等的改变进行恢复。然而您可以如下文主题所述，通过编写事务事件来编写恢复变量和集合的脚本。在某些时候，您的脚本也可以显式的提交或终止一个事务，如向文件写数据失败时。

提交或终止脚本

因为 Transaction Server 跟踪事务处理，所以它决定事务是完全成功还是失败。脚本可以通过调用 ObjectContext.SetAbort 显式地声明终止一个事务。 例如，当一个事务在从一个组件收到错误消息、违反商业规范时（例如，帐户余额小于 0）或读写文件等非事务性操作失败时，脚本就需要终止该事务。如果页在事务完成之前超时，也必须终止事务。

编写事务事件

脚本本身不能决定事务是成功还是失败。但是，可以编写提交或终止事务时被调用的事件。例如，假设有一个确认银行帐户的脚本，并且您需要针对事务的不同状态将不同的页返回给用户，那么就可以使用 OnTransactionCommit 和 OnTransactionAbort 事件来编写对用户的不同响应。

<%@ TRANSACTION = Required %>

<%
'Buffer output so that different pages can be displayed.
Response.Buffer = True
%>

<HTML>
<BODY>
<H1>Welcome to the online banking service</H1>

<%
Set BankAction = Server.CreateObject("MyExample.BankComponent")
BankAction.Deposit(Request("AcctNum"))
%>

<P>Thank you.  Your transaction is being processed.</P>
</BODY>
</HTML>

<%
' Display this page if the transaction succeeds.
Sub OnTransactionCommit()
  Response.Write "<HTML>"
  Response.Write "<BODY>"
  Response.Write "Thank you.  Your account has been credited."
  Response.Write "</BODY>"
  Response.Write "</HTML>"
  Response.Flush()
end sub
%>

<%
' Display this page if the transaction fails.
Sub OnTransactionAbort()
  Response.Clear()
  Response.Write "<HTML>"
  Response.Write "<BODY>"
  Response.Write "We are unable to complete your transaction."
  Response.Write "</BODY>"
  Response.Write "</HTML>"
  Response.Flush()
End sub
%>

在 MTS 资源管理器中登记一个组件

为了参与一个事务，组件必须在 MTS 包中登记，而且必须被配置为需要事务。例如，如果您的脚本是通过调用两个组件来处理订单的，一个更新库存数据库，另一个更新付款数据库。那么，这两个组件就要在同一个事务环境中运行。Transaction Server 保证如果任意一个组件失败，那么将不会有数据库被更新。某些组件不需要事务；例如，Ad Rotator 组件。

注册和配置事务性组件可使用 MTS 资源管理器。必须将事务的属性设置为需要事务或需要新事务。事务组件必须在 MTS 包中注册。不要将组件放在 IIS 内部进程包中，而应该创建自己的包。通常，应将所有的组件放在一个组件库中。组件库的组件可被多个 ASP 应用程序使用并以 ASP 应用程序进程运行。使用 MTS 资源管理器可创建新的包并将包的 Activation 属性设置为 Library。

也可以在 Server 包中注册事务性组件。Server 包通常以服务器上的一个独立的进程运行。如果希望使用基于职能组的安全性检查或希望您的组件可被远程计算机上的应用程序访问，可对事务性组件使用 Server 包。

要使用 MTS 资源管理器，必须安装 Microsoft Transaction Server。

对象作用域

一般情况下，不要将从 MTS 组件中创建的对象存储在 ASP Application 或 Session 对象中。 MTS 对象在事务完成后消失。因为 Session 对象和 Application 对象是为在不同 ASP 页之间使用的对象实例设计的，所以不要用它们保存在事务结束时即被释放的对象。

ASP 脚本是已声名的事务的根，即起始点。任何事务性 ASP 页所使用的 MTS 对象都被认为是事务的一部分。当事务完成后，在页中使用的 MTS 对象将消失，其中包括存储在 Session 或 Application 对象中的对象。在此之后，从另一个事务性页中调用会话作用域或应用程序作用域对象的尝试都将失败。

事务排队

从一个远程服务器对数据库的更新可能因为网络延迟或故障而导致事务延迟或终止。因为事务的所有部分都必须提交，所以应用程序将可能挂起，等待远程服务器的提交或终止消息，也可能由于无法发送数据库更新而导致事务被放弃。

对于必须同时完成的更新，正确的做法是在事务的所有参与者都能够提交之前，终止事务或推迟完成事务。例如，航空公司的定票程序应该同时完成对客户的银行帐号计入借方和对航空公司的银行帐户计入贷方。如果一个更新属于事务整体的一部分，但可能晚于其他更新，您可能不希望让客户等待整个更新过程的完成。例如，机票预定事务可能也要向食品供应商发送食品订单或更新客户的旅程津贴。这些操作虽然也必须完成，但可以晚一些。

Microsoft Message Queue Server 使您能够将一个或一组更新捆绑到一个事务性消息中送给远程服务器。Message Queue Server 保证更新将被发送给远程服务器，即使目前网络不可用。您的应用将收到一个提交消息，从而可以继续处理事务。


使用国际站点

在 Internet 或 Intranet 上发布消息的一个优点是您可以建立一个用户可以从不同国家（地区）访问的国际化 Web 站点。用户可以申请已被本地化为当地语言的网页，使用浏览器的本地化版本阅读。在建立一个包含有多种语言网页的 Web 站点时，需要转换在浏览器与 Web 服务器间或 ASP 脚本与 ActiveX 组件间传递的字符串。例如，如果一个日文浏览器在 HTTP 请求中发送了表格或查询字符串值，此字符串必须从浏览器的日文字符集转化为 ASP 用于处理脚本的字符集。

如果 Web 站点上的所有页都用 Web 服务器所使用的默认字符集书写，那么 ASP 将自动进行转换。但是，如果网页是用其他的字符集写的，就必须用 ASP 命令指明如何转换字符串。例如，如果您的站点既有日文字符集的网页，又有中文字符集的网页，就必须指明 ASP 处理某一特定页时所用的字符集。

ASP 也提供了支持不同地区文化习惯的命令，如货币、时间和日期格式。同字符串转换命令一样，如果您的脚本没有使用 Web 服务器的默认现场，则要使用现场命令。

设置字符串转换代码页

代码页是一个内部表，操作系统用它将符号（字母、数字和标点符号）映射为字符编号。不同的代码页支持不同国家（地区）所使用的字符集。代码页通过编号引用，例如，代码页 932 代表日文字符集，代码页 950 代表繁体中文字符集。

Active Server Pages 和 ActiveX 脚本引擎在内部使用 Unicode，这是一种 16 位固定长度的字符编码标准。如果您编写的所有页都使用 Web 服务器的默认代码页，则 ASP 将自动转换字符串。如果您的脚本不使用 Web 服务器的默认代码页，则应该指明所用的代码页以便字符串在 ASP 和脚本引擎间传递时能被正确转换。另外，您也可以为在浏览器与脚本间或 ActiveX 组件与脚本间传递的字符串指定代码页。

要为 ASP 页指定代码页，可使用 CODEPAGE 指令。例如，设置日文代码页，可使用以下指令：

<%@ CODEPAGE= 932 %>

当 ASP 处理这一页的内容和脚本时，将使用您指定的代码页来决定如何将脚本中的字符从您的脚本的字符集转化为 Unicode。例如，在 ANSI 中代表字母 "a" 的值将被转化为在 Unicode 中代表字母 "a" 的不同的值。

Active Server Pages 假定在服务器和浏览器间或脚本和 ActiveX 组件间传递的字符串的代码页与您为脚本设置的代码页是相同的。若要指定不同的代码页，可以设置 Session.CodePage 属性，从而覆盖 CODEPAGE 设置。例如，您使用 JIS 书写脚本，但却要响应使用 UTF-8 的客户程序，（JIS 和 UTF-8 是标准日文字符集的两种不同的字符编码）。

Session.CodePage 默认设置为 CODEPAGE 指令的值；对该属性的设置将覆盖当前的 CODEPAGE 设置。例如，要将代码页改为繁体中文，可使用如下命令：

<% Session.CodePage = 950 %>

如果您只是临时更改部分脚本的代码页，在此之后一定要将 Session.CodePage 设置为原来的值。以下脚本显示如何临时更改代码页：

<!-- Welcome to my home page in Japanese, code page 932 --!>
<%@ CodePage = 932 %>
...
<% Session("OriginalCodePage") = Session.CodePage %>
<!-- Look up name in Chinese, code page 950 --!>
<% Session.CodePage = 950 %>
<% Sender = ReadMailHeader("Sender") %>
<% Found = FindFriend("Sender") %>
<!-- Restore the original code page --!>
<% Session.CodePage =  Session("OriginalCodePage") %>
<% If Found == TRUE
    ReplyWithPersonalizedForm()
     else
    ReplyWithBusinessForm()
%>

设置现场标识

现场是与用户语言相关的一组用户首选项信息。现场决定如何格式化日期和时间、项目；如何按字母排序以及如何比较字符串。现场标识 (LCID) 是唯一定义现场的 32 位数值。如果您没有为脚本指定不同的现场，那么 ASP 将使用 Web 服务器的默认现场。

要为 ASP 页设置现场标识，可使用 LCID 指令。例如，要设置日文现场，可使用下列现场 ID：

<%@ LCID =  1041 %>

LCID 指令告诉 ASP 书写脚本所用的现场。如果要更改脚本的输入或输出现场，可使用 Session.LCID 属性。例如，要将现场设置为标准法语，可使用如下命令：

<% Session.LCID = 1036 %>

Session.LCID 的默认设置为 LCID 指令的设置。在脚本中设置 Session.LCID 的值将覆盖默认设置。


编写跨平台应用程序

ASP 应用程序可在运行 Windows NT 4.0 或 Windows 95 及其更新版本的操作系统的计算机上运行。另外，可在 Macintosh 上运行 streamline 版本的 ASP。因为在 Windows 95 和 Macintosh 上的 Personal Web Server 是为个人发布设计的，所以在对 ASP 应用的支持方面有些不同。您可以在 Windows NT Workstation 或 Windows NT Server 的服务器上十分方便地运行在个人发布平台上开发的应用程序。本主题介绍各平台间的不同之处。

在 Macintosh 上的 ASP

Macintosh 版的 ASP 是针对个人发布设计的，并提供了 ASP 脚本的简单接口。因此，某些在 Windows 平台拥有的 ASP 特性在 Macintosh 上不被支持。详细信息，请参阅 Macintosh ASP 文档。

Macintosh 版的 ASP 提供了在 Windows 平台上不能自动获得的内建对象。Windows 平台拥有提供这些对象的组件；但您必须先在应用程序的 Global.asa 文件中声明这些对象，然后才能使您的脚本不必修改即可运行于 Windows 平台。

Windows 95 上的 ASP

Windows 95 或其后的版本是作为个人发布平台设计的。虽然它完全支持运行 ASP 应用程序，但个人 Web 管理器并不具有 Web 开发人员所需的较复杂的管理特性，如更改脚本和会话超时。

Windows NT Workstation 上的 ASP

Windows NT Workstation 是支持所有 ASP 脚本特性的完整开发平台。作为默认的管理工具，个人 Web 管理器是为非专职服务器管理员的 Web 管理员设计的。对于希望在 ASP 应用程序开发与调试期间全面控制服务器站点的开发人员来说，Internet 服务管理器是一个合适的管理工具。可以通过运行 Personal Web Server 的安装程序来安装 Internet 服务管理器。